blob: 7be50171f8aea7fadce36f61139578a7172272a9 [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 Yu9236c432013-10-18 11:29:25 -070017
Yingdi Yu4685b1b2013-10-18 17:05:02 -070018#ifndef Q_MOC_RUN
Yingdi Yu348f5ea2014-03-01 14:47:25 -080019#include <ndn-cpp-dev/util/crypto.hpp>
20#include <ndn-cpp-dev/util/io.hpp>
21#include <ndn-cpp-dev/security/sec-rule-relative.hpp>
Yingdi Yufa4ce792014-02-06 18:09:22 -080022#include <ndn-cpp-dev/security/validator-regex.hpp>
Yingdi Yu72781e52013-11-06 23:00:21 -080023#include <cryptopp/base64.h>
Yingdi Yu348f5ea2014-03-01 14:47:25 -080024#include <cryptopp/files.h>
25#include <cryptopp/sha.h>
26#include <boost/asio.hpp>
27#include <boost/tokenizer.hpp>
28#include <boost/filesystem.hpp>
Yingdi Yuec3d9a32013-10-18 18:35:09 -070029#include "logging.h"
Yingdi Yu4685b1b2013-10-18 17:05:02 -070030#endif
Yingdi Yu9236c432013-10-18 11:29:25 -070031
32using namespace ndn;
Yingdi Yu76dd8002013-12-24 11:16:32 +080033using namespace std;
Yingdi Yu348f5ea2014-03-01 14:47:25 -080034namespace fs = boost::filesystem;
Yingdi Yu9236c432013-10-18 11:29:25 -070035
Yingdi Yu348f5ea2014-03-01 14:47:25 -080036INIT_LOGGER("chronos.ContactManager");
Yingdi Yuec3d9a32013-10-18 18:35:09 -070037
Yingdi Yufa4ce792014-02-06 18:09:22 -080038namespace chronos{
Yingdi Yu4685b1b2013-10-18 17:05:02 -070039
Yingdi Yu348f5ea2014-03-01 14:47:25 -080040static const uint8_t DNS_RP_SEPARATOR[2] = {0xF0, 0x2E}; // %F0.
41
Yingdi Yufa4ce792014-02-06 18:09:22 -080042ContactManager::ContactManager(shared_ptr<Face> face,
43 QObject* parent)
44 : QObject(parent)
Yingdi Yufa4ce792014-02-06 18:09:22 -080045 , m_face(face)
Yingdi Yu348f5ea2014-03-01 14:47:25 -080046 , m_dnsListenerId(0)
Yingdi Yufa4ce792014-02-06 18:09:22 -080047{
Yingdi Yu76dd8002013-12-24 11:16:32 +080048 initializeSecurity();
Yingdi Yu9236c432013-10-18 11:29:25 -070049}
50
51ContactManager::~ContactManager()
Yingdi Yu6eabbd72013-12-27 08:44:12 +080052{}
Yingdi Yu9236c432013-10-18 11:29:25 -070053
Yingdi Yu348f5ea2014-03-01 14:47:25 -080054// private methods
Yingdi Yu76dd8002013-12-24 11:16:32 +080055void
56ContactManager::initializeSecurity()
57{
Yingdi Yu348f5ea2014-03-01 14:47:25 -080058 fs::path anchorPath = fs::path(getenv("HOME")) / ".chronos" / "anchor.cert";
59 shared_ptr<IdentityCertificate> anchor = io::load<IdentityCertificate>(anchorPath.c_str());
Yingdi Yufa4ce792014-02-06 18:09:22 -080060
Yingdi Yu348f5ea2014-03-01 14:47:25 -080061 shared_ptr<ValidatorRegex> validator = make_shared<ValidatorRegex>(m_face);
62 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><ENDORSED>",
63 "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
64 "==", "\\1", "\\1\\2", true));
65 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><><ENDORSEE>",
66 "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
67 "==", "\\1", "\\1\\2", true));
68 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
69 "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
70 "==", "\\1", "\\1\\2", true));
71 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
72 "^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$",
73 "==", "\\1", "\\1\\2", true));
74 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
75 "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
76 ">", "\\1\\2", "\\1", true));
77 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
78 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
79 "==", "\\1", "\\1\\2", true));
80 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^(<>*)$",
81 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
82 ">", "\\1", "\\1\\2", true));
83 validator->addTrustAnchor(anchor);
84 m_validator = validator;
Yingdi Yu76dd8002013-12-24 11:16:32 +080085}
86
87void
Yingdi Yufa4ce792014-02-06 18:09:22 -080088ContactManager::fetchCollectEndorse(const Name& identity)
Yingdi Yub2e747d2013-11-05 23:06:43 -080089{
90 Name interestName = identity;
91 interestName.append("DNS").append("ENDORSED");
92
Yingdi Yu76dd8002013-12-24 11:16:32 +080093 Interest interest(interestName);
Yingdi Yuf8f572d2014-01-13 11:19:47 -080094 interest.setInterestLifetime(1000);
Yingdi Yufa4ce792014-02-06 18:09:22 -080095 interest.setMustBeFresh(true);
Yingdi Yu76dd8002013-12-24 11:16:32 +080096
Yingdi Yufa4ce792014-02-06 18:09:22 -080097 OnDataValidated onValidated = bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
98 OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsCollectEndorseValidationFailed, this, _1, identity);
Yingdi Yu348f5ea2014-03-01 14:47:25 -080099 TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, _1, identity);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800100
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800101 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800102}
103
104void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800105ContactManager::fetchEndorseCertificateInternal(const Name& identity, int certIndex)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800106{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800107 shared_ptr<EndorseCollection> endorseCollection = m_bufferedContacts[identity].m_endorseCollection;
108
109 if(certIndex >= endorseCollection->endorsement_size())
110 prepareEndorseInfo(identity);
111
112 Name interestName(endorseCollection->endorsement(certIndex).certname());
113
Yingdi Yu76dd8002013-12-24 11:16:32 +0800114 Interest interest(interestName);
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800115 interest.setInterestLifetime(1000);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800116 interest.setMustBeFresh(true);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800117
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800118 m_face->expressInterest(interest,
119 bind(&ContactManager::onEndorseCertificateInternal,
120 this, _1, _2, identity, certIndex,
121 endorseCollection->endorsement(certIndex).hash()),
122 bind(&ContactManager::onEndorseCertificateInternalTimeout,
123 this, _1, identity, certIndex));
Yingdi Yu76dd8002013-12-24 11:16:32 +0800124}
125
Yingdi Yu76dd8002013-12-24 11:16:32 +0800126void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800127ContactManager::prepareEndorseInfo(const Name& identity)
Yingdi Yu76dd8002013-12-24 11:16:32 +0800128{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800129 // _LOG_DEBUG("prepareEndorseInfo");
130 const Profile& profile = m_bufferedContacts[identity].m_selfEndorseCert->getProfile();
Yingdi Yu76dd8002013-12-24 11:16:32 +0800131
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800132 shared_ptr<EndorseInfo> endorseInfo = make_shared<EndorseInfo>();
133 m_bufferedContacts[identity].m_endorseInfo = endorseInfo;
134
135 Profile::const_iterator pIt = profile.begin();
136 Profile::const_iterator pEnd = profile.end();
137
138 map<string, int> endorseCount;
139 for(; pIt != pEnd; pIt++)
140 {
141 // _LOG_DEBUG("prepareEndorseInfo: profile[" << pIt->first << "]: " << pIt->second);
142 endorseCount[pIt->first] = 0;
143 }
144
145 int endorseCertCount = 0;
146
147 vector<shared_ptr<EndorseCertificate> >::const_iterator cIt = m_bufferedContacts[identity].m_endorseCertList.begin();
148 vector<shared_ptr<EndorseCertificate> >::const_iterator cEnd = m_bufferedContacts[identity].m_endorseCertList.end();
149
150 for(; cIt != cEnd; cIt++, endorseCertCount++)
151 {
152 shared_ptr<Contact> contact = getContact((*cIt)->getSigner().getPrefix(-1));
153 if(!static_cast<bool>(contact))
154 continue;
155
156 if(!contact->isIntroducer()
157 || !contact->canBeTrustedFor(profile.getIdentityName()))
158 continue;
159
160 if(!Validator::verifySignature(**cIt, contact->getPublicKey()))
161 continue;
162
163 const Profile& tmpProfile = (*cIt)->getProfile();
164 if(tmpProfile != profile)
165 continue;
166
167 const vector<string>& endorseList = (*cIt)->getEndorseList();
168 vector<string>::const_iterator eIt = endorseList.begin();
169 for(; eIt != endorseList.end(); eIt++)
170 endorseCount[*eIt] += 1;
171 }
172
173 pIt = profile.begin();
174 pEnd = profile.end();
175 for(; pIt != pEnd; pIt++)
176 {
177 EndorseInfo::Endorsement* endorsement = endorseInfo->add_endorsement();
178 endorsement->set_type(pIt->first);
179 endorsement->set_value(pIt->second);
180 stringstream ss;
181 ss << endorseCount[pIt->first] << "/" << endorseCertCount;
182 endorsement->set_endorse(ss.str());
183 }
184
185 emit contactEndorseInfoReady (*endorseInfo);
186}
187
188void
189ContactManager::onDnsSelfEndorseCertValidated(const shared_ptr<const Data>& data,
190 const Name& identity)
191{
192 try
193 {
194 Data plainData;
195 plainData.wireDecode(data->getContent().blockFromValue());
196 shared_ptr<EndorseCertificate> selfEndorseCertificate = make_shared<EndorseCertificate>(boost::cref(plainData));
197 if(Validator::verifySignature(plainData, selfEndorseCertificate->getPublicKeyInfo()))
198 {
199 m_bufferedContacts[identity].m_selfEndorseCert = selfEndorseCertificate;
200 fetchCollectEndorse(identity);
201 }
202 else
203 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
204 }
205 catch(Block::Error& e)
206 {
207 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
208 }
209 catch(Data::Error& e)
210 {
211 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
212 }
213 catch(EndorseCertificate::Error& e)
214 {
215 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
216 }
217}
218
219void
220ContactManager::onDnsSelfEndorseCertValidationFailed(const shared_ptr<const Data>& data,
221 const Name& identity)
222{
223 // If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
224 // but let's stay with failure for now.
225 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
226}
227
228void
229ContactManager::onDnsSelfEndorseCertTimeoutNotify(const Interest& interest,
230 const Name& identity)
231{
232 // If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
233 // but let's stay with failure for now.
234 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
235}
236
237void
238ContactManager::onDnsCollectEndorseValidated(const shared_ptr<const Data>& data,
239 const Name& identity)
240{
241 shared_ptr<EndorseCollection> endorseCollection = make_shared<EndorseCollection>();
242 if(!endorseCollection->ParseFromArray(data->getContent().value(), data->getContent().value_size()))
243 {
244 m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
245 fetchEndorseCertificateInternal(identity, 0);
246 }
247 else
248 prepareEndorseInfo(identity);
249}
250
251void
252ContactManager::onDnsCollectEndorseValidationFailed(const shared_ptr<const Data>& data,
253 const Name& identity)
254{
255 prepareEndorseInfo(identity);
256}
257
258void
259ContactManager::onDnsCollectEndorseTimeoutNotify(const Interest& interest,
260 const Name& identity)
261{
262 // _LOG_DEBUG("onDnsCollectEndorseTimeoutNotify: " << interest.getName());
263 prepareEndorseInfo(identity);
264}
265
266void
267ContactManager::onEndorseCertificateInternal(const Interest& interest,
268 Data& data,
269 const Name& identity,
270 int certIndex,
271 string hash)
272{
273 stringstream ss;
274 {
275 using namespace CryptoPP;
276
277 SHA256 hash;
278 StringSource(data.wireEncode().wire(), data.wireEncode().size(), true,
279 new HashFilter(hash, new FileSink(ss)));
280 }
281
282 if(ss.str() == hash)
283 {
284 shared_ptr<EndorseCertificate> endorseCertificate = make_shared<EndorseCertificate>(boost::cref(data));
285 m_bufferedContacts[identity].m_endorseCertList.push_back(endorseCertificate);
286 }
287
288 fetchEndorseCertificateInternal(identity, certIndex+1);
289}
290
291void
292ContactManager::onEndorseCertificateInternalTimeout(const Interest& interest,
293 const Name& identity,
294 int certIndex)
295{
296 fetchEndorseCertificateInternal(identity, certIndex+1);
297}
298
299void
300ContactManager::collectEndorsement()
301{
302 {
303 boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
304 m_collectCount = m_contactList.size();
305
306 ContactList::iterator it = m_contactList.begin();
307 ContactList::iterator end = m_contactList.end();
308
309 for(; it != end ; it++)
310 {
311 Name interestName = (*it)->getNameSpace();
312 interestName.append("DNS").append(m_identity.wireEncode()).append("ENDORSEE");
313
314 Interest interest(interestName);
315 interest.setInterestLifetime(1000);
316
317 OnDataValidated onValidated = bind(&ContactManager::onDnsEndorseeValidated, this, _1);
318 OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1);
319 TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsEndorseeTimeoutNotify, this, _1);
320
321 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
322 }
Yingdi Yu76dd8002013-12-24 11:16:32 +0800323 }
324}
325
326void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800327ContactManager::onDnsEndorseeValidated(const shared_ptr<const Data>& data)
Yingdi Yuae8217c2013-11-09 00:03:26 -0800328{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800329 Data endorseData;
330 endorseData.wireDecode(data->getContent().blockFromValue());
Yingdi Yu76dd8002013-12-24 11:16:32 +0800331
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800332 EndorseCertificate endorseCertificate(endorseData);
333 m_contactStorage->updateCollectEndorse(endorseCertificate);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800334
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800335 decreaseCollectStatus();
Yingdi Yu76dd8002013-12-24 11:16:32 +0800336}
Yingdi Yuae8217c2013-11-09 00:03:26 -0800337
338void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800339ContactManager::onDnsEndorseeValidationFailed(const shared_ptr<const Data>& data)
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700340{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800341 decreaseCollectStatus();
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700342}
343
Yingdi Yub2e747d2013-11-05 23:06:43 -0800344void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800345ContactManager::onDnsEndorseeTimeoutNotify(const Interest& interest)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800346{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800347 decreaseCollectStatus();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800348}
349
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800350void
351ContactManager::decreaseCollectStatus()
Yingdi Yub2e747d2013-11-05 23:06:43 -0800352{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800353 int count;
354 {
355 boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
356 m_collectCount--;
357 count = m_collectCount;
358 }
Yingdi Yub2e747d2013-11-05 23:06:43 -0800359
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800360 if(count == 0)
361 publishCollectEndorsedDataInDNS();
362}
Yingdi Yub2e747d2013-11-05 23:06:43 -0800363
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800364void
365ContactManager::publishCollectEndorsedDataInDNS()
366{
367 Name dnsName = m_identity;
368 dnsName.append("DNS").append("ENDORSED").appendVersion();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800369
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800370 Data data;
371 data.setName(dnsName);
372
373 EndorseCollection endorseCollection;
374 m_contactStorage->getCollectEndorse(endorseCollection);
375
376 OBufferStream os;
377 endorseCollection.SerializeToOstream(&os);
378
379 data.setContent(os.buf());
380 m_keyChain.signByIdentity(data, m_identity);
381
382 m_contactStorage->updateDnsOthersEndorse(data);
383 m_face->put(data);
384}
385
386void
387ContactManager::onIdentityCertValidated(const shared_ptr<const Data>& data)
388{
389 shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(boost::cref(*data));
390 m_bufferedIdCerts[cert->getName()] = cert;
391 decreaseIdCertCount();
392}
393
394void
395ContactManager::onIdentityCertValidationFailed(const shared_ptr<const Data>& data)
396{
397 _LOG_DEBUG("ContactManager::onIdentityCertValidationFailed " << data->getName());
398 decreaseIdCertCount();
399}
400
401void
402ContactManager::onIdentityCertTimeoutNotify(const Interest& interest)
403{
404 _LOG_DEBUG("ContactManager::onIdentityCertTimeoutNotify: " << interest.getName());
405 decreaseIdCertCount();
406}
407
408void
409ContactManager::decreaseIdCertCount()
410{
411 int count;
412 {
413 boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
414 m_idCertCount--;
415 count = m_idCertCount;
416 }
417
418 if(count == 0)
419 {
420 QStringList certNameList;
421 QStringList nameList;
422
423 BufferedIdCerts::const_iterator it = m_bufferedIdCerts.begin();
424 BufferedIdCerts::const_iterator end = m_bufferedIdCerts.end();
425 for(; it != end; it++)
426 {
427 certNameList << QString::fromStdString(it->second->getName().toUri());
428 Profile profile(*(it->second));
429 nameList << QString::fromStdString(profile.get("name"));
430 }
431
432 emit idCertNameListReady(certNameList);
433 emit nameListReady(nameList);
434 }
Yingdi Yub2e747d2013-11-05 23:06:43 -0800435}
436
Yingdi Yu76dd8002013-12-24 11:16:32 +0800437shared_ptr<EndorseCertificate>
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800438ContactManager::getSignedSelfEndorseCertificate(const Profile& profile)
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700439{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800440 Name certificateName = m_keyChain.getDefaultCertificateNameForIdentity(m_identity);
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700441
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800442 shared_ptr<IdentityCertificate> signingCert = m_keyChain.getCertificate(certificateName);
Yingdi Yu72781e52013-11-06 23:00:21 -0800443
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700444 vector<string> endorseList;
445 Profile::const_iterator it = profile.begin();
446 for(; it != profile.end(); it++)
447 endorseList.push_back(it->first);
448
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800449 shared_ptr<EndorseCertificate> selfEndorseCertificate =
450 shared_ptr<EndorseCertificate>(new EndorseCertificate(*signingCert, profile, endorseList));
451
452 m_keyChain.sign(*selfEndorseCertificate, certificateName);
453
454 return selfEndorseCertificate;
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700455}
456
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700457void
Yingdi Yu76dd8002013-12-24 11:16:32 +0800458ContactManager::publishSelfEndorseCertificateInDNS(const EndorseCertificate& selfEndorseCertificate)
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700459{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800460 Name dnsName = m_identity;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800461 dnsName.append("DNS").append("PROFILE").appendVersion();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800462
463 Data data;
Yingdi Yu76dd8002013-12-24 11:16:32 +0800464 data.setName(dnsName);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800465 data.setContent(selfEndorseCertificate.wireEncode());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800466 data.setFreshnessPeriod(1000);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800467
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800468 m_keyChain.signByIdentity(data, m_identity);
469
470 m_contactStorage->updateDnsSelfProfileData(data);
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800471 m_face->put(data);
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700472}
473
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800474shared_ptr<EndorseCertificate>
475ContactManager::generateEndorseCertificate(const Name& identity)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800476{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800477 shared_ptr<Contact> contact = getContact(identity);
478 if(!static_cast<bool>(contact))
479 return shared_ptr<EndorseCertificate>();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800480
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800481 Name signerKeyName = m_keyChain.getDefaultKeyNameForIdentity(m_identity);
482
483 vector<string> endorseList;
484 m_contactStorage->getEndorseList(identity, endorseList);
485
486 shared_ptr<EndorseCertificate> cert =
487 shared_ptr<EndorseCertificate>(new EndorseCertificate(contact->getPublicKeyName(),
488 contact->getPublicKey(),
489 contact->getNotBefore(),
490 contact->getNotAfter(),
491 signerKeyName,
492 contact->getProfile(),
493 endorseList));
494 m_keyChain.signByIdentity(*cert, m_identity);
495 return cert;
496
497}
498
499void
500ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate)
501{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800502 Name endorsee = endorseCertificate.getPublicKeyName().getPrefix(-1);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800503 Name dnsName = m_identity;
504 dnsName.append("DNS")
505 .append(endorsee.wireEncode())
506 .append("ENDORSEE")
507 .appendVersion();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800508
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800509 Data data;
Yingdi Yu76dd8002013-12-24 11:16:32 +0800510 data.setName(dnsName);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800511 data.setContent(endorseCertificate.wireEncode());
Yingdi Yub2e747d2013-11-05 23:06:43 -0800512
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800513 m_keyChain.signByIdentity(data, m_identity);
514
515 m_contactStorage->updateDnsEndorseOthers(data, dnsName.get(-3).toEscapedString());
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800516 m_face->put(data);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800517}
518
519void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800520ContactManager::sendInterest(const Interest& interest,
521 const OnDataValidated& onValidated,
522 const OnDataValidationFailed& onValidationFailed,
523 const TimeoutNotify& timeoutNotify,
524 int retry /* = 1 */)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800525{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800526 m_face->expressInterest(interest,
527 bind(&ContactManager::onTargetData,
528 this, _1, _2, onValidated, onValidationFailed),
529 bind(&ContactManager::onTargetTimeout,
530 this, _1, retry, onValidated, onValidationFailed, timeoutNotify));
531}
Yingdi Yu76dd8002013-12-24 11:16:32 +0800532
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800533void
534ContactManager::onTargetData(const Interest& interest,
535 const Data& data,
536 const OnDataValidated& onValidated,
537 const OnDataValidationFailed& onValidationFailed)
538{
539 // _LOG_DEBUG("On receiving data: " << data.getName());
540 m_validator->validate(data, onValidated, onValidationFailed);
541}
Yingdi Yub2e747d2013-11-05 23:06:43 -0800542
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800543void
544ContactManager::onTargetTimeout(const Interest& interest,
545 int retry,
546 const OnDataValidated& onValidated,
547 const OnDataValidationFailed& onValidationFailed,
548 const TimeoutNotify& timeoutNotify)
549{
550 // _LOG_DEBUG("On interest timeout: " << interest.getName());
551 if(retry > 0)
552 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, retry-1);
553 else
554 timeoutNotify(interest);
555}
556
557void
558ContactManager::onDnsInterest(const Name& prefix, const Interest& interest)
559{
560 const Name& interestName = interest.getName();
561 shared_ptr<Data> data;
562
563 if(interestName.size() <= prefix.size())
564 return;
565
566 if(interestName.size() == (prefix.size()+1))
Yingdi Yub2e747d2013-11-05 23:06:43 -0800567 {
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800568 data = m_contactStorage->getDnsData("N/A", interestName.get(prefix.size()).toEscapedString());
569 if(static_cast<bool>(data))
570 m_face->put(*data);
571 return;
Yingdi Yub2e747d2013-11-05 23:06:43 -0800572 }
Yingdi Yub2e747d2013-11-05 23:06:43 -0800573
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800574 if(interestName.size() == (prefix.size()+2))
575 {
576 data = m_contactStorage->getDnsData(interestName.get(prefix.size()).toEscapedString(),
577 interestName.get(prefix.size()+1).toEscapedString());
578 if(static_cast<bool>(data))
579 m_face->put(*data);
580 return;
581 }
582}
Yingdi Yub2e747d2013-11-05 23:06:43 -0800583
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800584void
585ContactManager::onDnsRegisterFailed(const Name& prefix, const string& failInfo)
586{
587 emit warning(QString(failInfo.c_str()));
588}
589
590
591// public slots
592void
593ContactManager::onIdentityUpdated(const QString& identity)
594{
595 m_identity = Name(identity.toStdString());
596
597 m_contactStorage = make_shared<ContactStorage>(m_identity);
598
599 if(m_dnsListenerId)
600 m_face->unsetInterestFilter(m_dnsListenerId);
601
602 Name dnsPrefix;
603 dnsPrefix.append(m_identity).append("DNS");
604 m_dnsListenerId = m_face->setInterestFilter(dnsPrefix,
605 bind(&ContactManager::onDnsInterest, this, _1, _2),
606 bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));
607
608 m_contactList.clear();
609 m_contactStorage->getAllContacts(m_contactList);
610
611 m_bufferedContacts.clear();
612
613 collectEndorsement();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800614}
615
Yingdi Yuae8217c2013-11-09 00:03:26 -0800616void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800617ContactManager::onFetchContactInfo(const QString& identity)
Yingdi Yuae8217c2013-11-09 00:03:26 -0800618{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800619 // try to fetch self-endorse-certificate via DNS PROFILE first.
620 Name identityName(identity.toStdString());
621 Name interestName;
622 interestName.append(identityName).append("DNS").append("PROFILE");
Yingdi Yu76dd8002013-12-24 11:16:32 +0800623
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800624 // _LOG_DEBUG("onFetchContactInfo " << identity.toStdString() << " profile: " << interestName);
625
626 Interest interest(interestName);
627 interest.setInterestLifetime(1000);
628 interest.setMustBeFresh(true);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800629
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800630 OnDataValidated onValidated = bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
631 OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, identityName);
632 TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsSelfEndorseCertTimeoutNotify, this, _1, identityName);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800633
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800634 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
635}
Yingdi Yu76dd8002013-12-24 11:16:32 +0800636
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800637void
638ContactManager::onAddFetchedContact(const QString& identity)
639{
640 // _LOG_DEBUG("onAddFetchedContact");
641
642 Name identityName(identity.toStdString());
643
644 BufferedContacts::const_iterator it = m_bufferedContacts.find(identityName);
645 if(it != m_bufferedContacts.end())
646 {
647 Contact contact(*(it->second.m_selfEndorseCert));
648 // _LOG_DEBUG("onAddFetchedContact: contact ready");
649 try
650 {
651 m_contactStorage->addContact(contact);
652 m_bufferedContacts.erase(identityName);
653
654 m_contactList.clear();
655 m_contactStorage->getAllContacts(m_contactList);
656
657 onWaitForContactList();
658 }
659 catch(ContactStorage::Error& e)
660 {
661 emit warning(QString::fromStdString(e.what()));
662 }
663 }
664 else
665 {
666 emit warning(QString("Failure: no information of %1").arg(identity));
667 }
668}
669
670void
671ContactManager::onUpdateProfile()
672{
673 // Get current profile;
674 shared_ptr<Profile> newProfile = m_contactStorage->getSelfProfile();
675 if(!static_cast<bool>(newProfile))
Yingdi Yuae8217c2013-11-09 00:03:26 -0800676 return;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800677
678 _LOG_DEBUG("ContactManager::onUpdateProfile: getProfile");
679
680 shared_ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(*newProfile);
681
682 m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate);
683
684 publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
685}
686
687void
688ContactManager::onRefreshBrowseContact()
689{
690 return; // the website info is not available.
691
692 std::vector<std::string> bufferedIdCertNames;
693 try
694 {
695 using namespace boost::asio::ip;
696 tcp::iostream request_stream;
697 request_stream.expires_from_now(boost::posix_time::milliseconds(5000));
698 request_stream.connect("ndncert.named-data.net","80");
699 if(!request_stream)
700 {
701 emit warning(QString::fromStdString("Fail to fetch certificate directory! #1"));
702 return;
703 }
704
705 request_stream << "GET /cert/list/ HTTP/1.0\r\n";
706 request_stream << "Host: ndncert.named-data.net\r\n\r\n";
707 request_stream.flush();
708
709 string line1;
710 std::getline(request_stream,line1);
711 if (!request_stream)
712 {
713 emit warning(QString::fromStdString("Fail to fetch certificate directory! #2"));
714 return;
715 }
716
717 std::stringstream response_stream(line1);
718 std::string http_version;
719 response_stream >> http_version;
720 unsigned int status_code;
721 response_stream >> status_code;
722 std::string status_message;
723 std::getline(response_stream,status_message);
724
725 if (!response_stream||http_version.substr(0,5)!="HTTP/")
726 {
727 emit warning(QString::fromStdString("Fail to fetch certificate directory! #3"));
728 return;
729 }
730 if (status_code!=200)
731 {
732 emit warning(QString::fromStdString("Fail to fetch certificate directory! #4"));
733 return;
734 }
735 vector<string> headers;
736 std::string header;
737 while (std::getline(request_stream, header) && header != "\r")
738 headers.push_back(header);
739
740 std::istreambuf_iterator<char> stream_iter (request_stream);
741 std::istreambuf_iterator<char> end_of_stream;
742
743 typedef boost::tokenizer< boost::escaped_list_separator<char>, std::istreambuf_iterator<char> > tokenizer_t;
744 tokenizer_t certItems (stream_iter, end_of_stream,boost::escaped_list_separator<char>('\\', '\n', '"'));
745
746 for (tokenizer_t::iterator it = certItems.begin(); it != certItems.end (); it++)
747 if (!it->empty())
748 bufferedIdCertNames.push_back(*it);
749 }
750 catch(std::exception &e)
751 {
752 emit warning(QString::fromStdString("Fail to fetch certificate directory! #N"));
753 }
754
755 {
756 boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
757 m_idCertCount = bufferedIdCertNames.size();
Yingdi Yuae8217c2013-11-09 00:03:26 -0800758 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800759 m_bufferedIdCerts.clear();
760
761 std::vector<std::string>::const_iterator it = bufferedIdCertNames.begin();
762 std::vector<std::string>::const_iterator end = bufferedIdCertNames.end();
763 for(; it != end; it++)
764 {
765 Name certName(*it);
766
767 Interest interest(certName);
768 interest.setInterestLifetime(1000);
769 interest.setMustBeFresh(true);
770
771 OnDataValidated onValidated = bind(&ContactManager::onIdentityCertValidated, this, _1);
772 OnDataValidationFailed onValidationFailed = bind(&ContactManager::onIdentityCertValidationFailed, this, _1);
773 TimeoutNotify timeoutNotify = bind(&ContactManager::onIdentityCertTimeoutNotify, this, _1);
774
775 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
776 }
777
Yingdi Yuae8217c2013-11-09 00:03:26 -0800778}
779
Yingdi Yu72232692013-11-12 17:50:21 -0800780void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800781ContactManager::onFetchIdCert(const QString& qCertName)
Yingdi Yu72232692013-11-12 17:50:21 -0800782{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800783 Name certName(qCertName.toStdString());
784 if(m_bufferedIdCerts.find(certName) != m_bufferedIdCerts.end())
785 {
786 emit idCertReady(*m_bufferedIdCerts[certName]);
787 }
Yingdi Yu72232692013-11-12 17:50:21 -0800788}
Yingdi Yuae8217c2013-11-09 00:03:26 -0800789
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800790void
791ContactManager::onAddFetchedContactIdCert(const QString& qCertName)
792{
793 Name certName(qCertName.toStdString());
794 Name identity = IdentityCertificate::certificateNameToPublicKeyName(certName).getPrefix(-1);
795
796 BufferedIdCerts::const_iterator it = m_bufferedIdCerts.find(certName);
797 if(it != m_bufferedIdCerts.end())
798 {
799 Contact contact(*it->second);
800 try
801 {
802 m_contactStorage->addContact(contact);
803 m_bufferedIdCerts.erase(certName);
804
805 m_contactList.clear();
806 m_contactStorage->getAllContacts(m_contactList);
807
808 onWaitForContactList();
809 }
810 catch(ContactStorage::Error& e)
811 {
812 emit warning(QString::fromStdString(e.what()));
813 }
814 }
815 else
816 emit warning(QString("Failure: no information of %1").arg(QString::fromStdString(identity.toUri())));
817}
818
819void
820ContactManager::onWaitForContactList()
821{
822 ContactList::const_iterator it = m_contactList.begin();
823 ContactList::const_iterator end = m_contactList.end();
824
825 QStringList aliasList;
826 QStringList idList;
827 for(; it != end; it++)
828 {
829 aliasList << QString((*it)->getAlias().c_str());
830 idList << QString((*it)->getNameSpace().toUri().c_str());
831 }
832
833 emit contactAliasListReady(aliasList);
834 emit contactIdListReady(idList);
835}
836
837void
838ContactManager::onWaitForContactInfo(const QString& identity)
839{
840 ContactList::const_iterator it = m_contactList.begin();
841 ContactList::const_iterator end = m_contactList.end();
842
843 for(; it != end; it++)
844 if((*it)->getNameSpace().toUri() == identity.toStdString())
845 emit contactInfoReady(QString((*it)->getNameSpace().toUri().c_str()),
846 QString((*it)->getName().c_str()),
847 QString((*it)->getInstitution().c_str()),
848 (*it)->isIntroducer());
849}
850
851void
852ContactManager::onRemoveContact(const QString& identity)
853{
854 m_contactStorage->removeContact(Name(identity.toStdString()));
855 m_contactList.clear();
856 m_contactStorage->getAllContacts(m_contactList);
857
858 onWaitForContactList();
859}
860
861void
862ContactManager::onUpdateAlias(const QString& identity, const QString& alias)
863{
864 m_contactStorage->updateAlias(Name(identity.toStdString()), alias.toStdString());
865 m_contactList.clear();
866 m_contactStorage->getAllContacts(m_contactList);
867
868 onWaitForContactList();
869}
870
871void
872ContactManager::onUpdateIsIntroducer(const QString& identity, bool isIntroducer)
873{
874 m_contactStorage->updateIsIntroducer(Name(identity.toStdString()), isIntroducer);
875}
876
877void
878ContactManager::onUpdateEndorseCertificate(const QString& identity)
879{
880 Name identityName(identity.toStdString());
881 shared_ptr<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identityName);
882
883 if(!static_cast<bool>(newEndorseCertificate))
884 return;
885
886 m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identityName);
887
888 publishEndorseCertificateInDNS(*newEndorseCertificate);
889}
890
891} // namespace chronos
Yingdi Yufa4ce792014-02-06 18:09:22 -0800892
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700893
894#if WAF
895#include "contact-manager.moc"
896#include "contact-manager.cpp.moc"
897#endif