blob: 2b834c65bcbdd0532836156cf5d747db110392a5 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2013, Regents of the University of California
* Yingdi Yu
*
* BSD license, See the LICENSE file for more information
*
* Author: Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "contact-manager.h"
#ifndef Q_MOC_RUN
#include <ndn.cxx/wrapper/wrapper.h>
#include <ndn.cxx/security/keychain.h>
#include <ndn.cxx/security/policy/simple-policy-manager.h>
#include <ndn.cxx/security/policy/identity-policy-rule.h>
#include <ndn.cxx/helpers/der/der.h>
#include <cryptopp/base64.h>
#include <fstream>
#include "logging.h"
#endif
using namespace ndn;
using namespace ndn::security;
INIT_LOGGER("ContactManager");
ContactManager::ContactManager(Ptr<ContactStorage> contactStorage,
Ptr<DnsStorage> dnsStorage,
QObject* parent)
: QObject(parent)
, m_contactStorage(contactStorage)
, m_dnsStorage(dnsStorage)
{
setKeychain();
m_wrapper = Ptr<Wrapper>(new Wrapper(m_keychain));
}
ContactManager::~ContactManager()
{
}
void
ContactManager::setKeychain()
{
Ptr<IdentityManager> identityManager = Ptr<IdentityManager>::Create();
Ptr<SimplePolicyManager> policyManager = Ptr<SimplePolicyManager>::Create();
Ptr<Keychain> keychain = Ptr<Keychain>(new Keychain(identityManager, policyManager, NULL));
policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<DNS>]*)<DNS><ENDORSED>",
"^([^<KEY>]*)<KEY>(<>*)[<ksk-.*><dsk-.*>]<ID-CERT>$",
"==", "\\1", "\\1\\2", true)));
policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<DNS>]*)<DNS><PROFILE>",
"^([^<KEY>]*)<KEY>(<>*)[<ksk-.*><dsk-.*>]<ID-CERT>$",
"==", "\\1", "\\1\\2", true)));
policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
"^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$",
"==", "\\1", "\\1\\2", true)));
policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
"^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
">", "\\1\\2", "\\1", true)));
policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
"^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
"==", "\\1", "\\1\\2", true)));
policyManager->addSigningPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<DNS>]*)<DNS><PROFILE>",
"^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>",
"==", "\\1", "\\1\\2", true)));
const string TrustAnchor("BIICqgOyEIWlKzDI2xX2hdq5Azheu9IVyewcV4uM7ylfh67Y8MIxF3tDCTx5JgEn\
HYMuCaYQm6XuaXTlVfDdWff/K7Xebq8IgGxjNBeU9eMf7Gy9iIMrRAOdBG0dBHmo\
67biGs8F+P1oh1FwKu/FN1AE9vh8HSOJ94PWmjO+6PvITFIXuI3QbcCz8rhvbsfb\
5X/DmfbJ8n8c4X3nVxrBm6fd4z8kOFOvvhgJImvqsow69Uy+38m8gJrmrcWMoPBJ\
WsNLcEriZCt/Dlg7EqqVrIn6ukylKCvVrxA9vm/cEB74J/N+T0JyMRDnTLm17gpq\
Gd75rhj+bLmpOMOBT7Nb27wUKq8gcXzeAADy+p1uZG4A+p1LRVkA+vVrc2stMTM4\
MzMyNTcyMAD6vUlELUNFUlQA+q39PgurHgAAAaID4gKF5vjua9EIr3/Fn8k1AdSc\
nEryjVDW3ikvYoSwjK7egTkAArq1BSc+C6sdAAHiAery+p1uZG4A+p1LRVkA+vVr\
c2stMTM4MzMyNTcyMAD6vUlELUNFUlQAAAAAAAGaFr0wggFjMCIYDzIwMTMxMTAx\
MTcxMTIyWhgPMjAxNDExMDExNzExMjJaMBkwFwYDVQQpExBORE4gVGVzdGJlZCBS\
b290MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA06x+elwzWCHa4I3b\
yrYCMAIVxQpRVLuOXp0h+BS+5GNgMVPi7+40o4zSJG+kiU8CIH1mtj8RQAzBX9hF\
I5VAyOC8nS8D8YOfBwt2yRDZPgt1E5PpyYUBiDYuq/zmJDL8xjxAlxrMzVOqD/uj\
/vkkcBM/T1t9Q6p1CpRyq+GMRbV4EAHvH7MFb6bDrH9t8DHEg7NPUCaSQBrd7PvL\
72P+QdiNH9zs/EiVzAkeMG4iniSXLuYM3z0gMqqcyUUUr6r1F9IBmDO+Kp97nZh8\
VCL+cnIEwyzAFAupQH5GoXUWGiee8oKWwH2vGHX7u6sWZsCp15NMSG3OC4jUIZOE\
iVUF1QIBEQAA");
string decoded;
CryptoPP::StringSource ss(reinterpret_cast<const unsigned char *>(TrustAnchor.c_str()),
TrustAnchor.size(),
true,
new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
Ptr<Blob> blob = Ptr<Blob>(new Blob(decoded.c_str(), decoded.size()));
Ptr<Data> data = Data::decodeFromWire(blob);
Ptr<IdentityCertificate>anchor = Ptr<IdentityCertificate>(new IdentityCertificate(*data));
policyManager->addTrustAnchor(anchor);
#ifdef _DEBUG
const string FakeAnchor("BIICqgOyEIVAaoHnQZIx5osAuY2fKte4HBSrxyam7MY6/kp+w47O1bGdd2KjeZKV\
zZzQd3EQorDC3KUPbB6ql30jYfspvo4OPSlIuDrkyROaoZ+MSKyzQYpB6CZcTjBa\
qcWYFOfwUlcWvkbd00X4bkc5PkcWpVdRrx+NCTiq9EXes//hOHpEJHMNsJUi45O+\
6M4OE6/sNEqs/ryHn2w1vCqwPpG8xzcd0prQUdCH2MGE77F+H0XFDuWp8mrT37Uw\
DUy7Ltm+7nDTHSQy2J3Zk4Q+0tjxCzSw4owEpwOHr+afdkuE3v9aB2NRQBBDCEmL\
Ykz4sYX3XE8MVFqRn1HHWCkszjDg+F0UAADy+p1uZG4A+p1LRVkA+vVrc2stMTM4\
MjkzNDE5OAD6vUlELUNFUlQA+s39/////95rc7MAAAGiA+IChaK1eVvzlkg6BJAw\
qiOpxRoezQ0hAHOBbPRLeBllxMN7AAK6tQUm3mtztQAB4gHq8vqdbmRuAPqdS0VZ\
APr1a3NrLTEzODI5MzQxOTgA+r1JRC1DRVJUAAAAAAABmhblMIIBaDAiGA8yMDEz\
MTAyODAwMDAwMFoYDzIwMzMxMDI4MDAwMDAwWjAcMBoGA1UEKRMTL25kbi9rc2st\
MTM4MjkzNDE5ODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK2htIFF\
/PH+SJsGOA6jhpFT74xfLJlgZNJOnKzl27HI2gupE0mainWj/HqVzdGxD6jOOReI\
sul+eQyEyBYq4e35pLmdJGlux/+UPQ51DD8jg04GrUPewV7+iGm6usp/7xEGHbah\
H2Grv/bsGrt6aRA8cKmdIc+rehxZCVFtiwSEHTnOWzn3lfZR5xnjF9aGX+uGo1hA\
gMwu1ECxg4H3O4z1tbTzji5+WH0RDsPRlgzQX6wAQH8btlQyoFJfljEA3QaOtDaB\
OcfegIlClzutmgJnK9i5ZLz2Mjvx49dlCWAVKg65vOXMLC/33jD9F+V8urwsBlOb\
F7Wh5ayeo8NBKDsCAwEAAQAA");
string decoded2;
CryptoPP::StringSource ss2(reinterpret_cast<const unsigned char *>(FakeAnchor.c_str()),
FakeAnchor.size(),
true,
new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded2)));
Ptr<Blob> blob2 = Ptr<Blob>(new Blob(decoded2.c_str(), decoded2.size()));
Ptr<Data> data2 = Data::decodeFromWire(blob2);
Ptr<IdentityCertificate>anchor2 = Ptr<IdentityCertificate>(new IdentityCertificate(*data2));
policyManager->addTrustAnchor(anchor2);
#endif
m_keychain = keychain;
}
void
ContactManager::fetchSelfEndorseCertificate(const ndn::Name& identity)
{
Name interestName = identity;
interestName.append("DNS").append("PROFILE");
Ptr<Interest> interestPtr = Ptr<Interest>(new Interest(interestName));
interestPtr->setChildSelector(Interest::CHILD_RIGHT);
Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&ContactManager::onDnsSelfEndorseCertificateVerified,
this,
_1,
identity),
boost::bind(&ContactManager::onDnsSelfEndorseCertificateTimeout,
this,
_1,
_2,
identity,
0),
boost::bind(&ContactManager::onDnsSelfEndorseCertificateUnverified,
this,
_1,
identity)));
m_wrapper->sendInterest(interestPtr, closure);
}
void
ContactManager::fetchCollectEndorse(const ndn::Name& identity)
{
Name interestName = identity;
interestName.append("DNS").append("ENDORSED");
Ptr<Interest> interestPtr = Ptr<Interest>(new Interest(interestName));
interestPtr->setChildSelector(Interest::CHILD_RIGHT);
interestPtr->setInterestLifetime(1);
Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&ContactManager::onDnsCollectEndorseVerified,
this,
_1,
identity),
boost::bind(&ContactManager::onDnsCollectEndorseTimeout,
this,
_1,
_2,
identity,
0),
boost::bind(&ContactManager::onDnsCollectEndorseUnverified,
this,
_1,
identity)));
m_wrapper->sendInterest(interestPtr, closure);
}
void
ContactManager::fetchKey(const ndn::Name& certName)
{
Name interestName = certName;
Ptr<Interest> interestPtr = Ptr<Interest>(new Interest(interestName));
interestPtr->setChildSelector(Interest::CHILD_RIGHT);
Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&ContactManager::onKeyVerified,
this,
_1,
certName),
boost::bind(&ContactManager::onKeyTimeout,
this,
_1,
_2,
certName,
0),
boost::bind(&ContactManager::onKeyUnverified,
this,
_1,
certName)));
m_wrapper->sendInterest(interestPtr, closure);
}
void
ContactManager::onDnsCollectEndorseVerified(Ptr<Data> data, const Name& identity)
{ emit collectEndorseFetched (*data); }
void
ContactManager::onDnsCollectEndorseTimeout(Ptr<Closure> closure, Ptr<Interest> interest, const Name& identity, int retry)
{ emit collectEndorseFetchFailed (identity); }
void
ContactManager::onDnsCollectEndorseUnverified(Ptr<Data> data, const Name& identity)
{ emit collectEndorseFetchFailed (identity); }
void
ContactManager::onKeyVerified(Ptr<Data> data, const Name& identity)
{
IdentityCertificate identityCertificate(*data);
Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(Profile(identityCertificate)));
Ptr<IdentityManager> identityManager = m_keychain->getIdentityManager();
Name certificateName = identityManager->getDefaultCertificateName ();
identityManager->signByCertificate(*profileData, certificateName);
EndorseCertificate endorseCertificate(identityCertificate, profileData);
identityManager->signByCertificate(endorseCertificate, certificateName);
emit contactKeyFetched (endorseCertificate);
}
void
ContactManager::onKeyUnverified(Ptr<Data> data, const Name& identity)
{ emit contactKeyFetchFailed (identity); }
void
ContactManager::onKeyTimeout(Ptr<Closure> closure, Ptr<Interest> interest, const Name& identity, int retry)
{ emit contactKeyFetchFailed(identity); }
void
ContactManager::updateProfileData(const Name& identity)
{
// _LOG_DEBUG("updateProfileData: " << identity.toUri());
// Get current profile;
Ptr<Profile> newProfile = m_contactStorage->getSelfProfile(identity);
if(NULL == newProfile)
return;
Ptr<Blob> newProfileBlob = newProfile->toDerBlob();
// Check if profile exists
Ptr<Blob> profileDataBlob = m_contactStorage->getSelfEndorseCertificate(identity);
if(NULL != profileDataBlob)
{
Ptr<Data> plainData = Data::decodeFromWire(profileDataBlob);
EndorseCertificate oldEndorseCertificate(*plainData);
// _LOG_DEBUG("Certificate converted!");
const Blob& oldProfileBlob = oldEndorseCertificate.getProfileData()->content();
if(oldProfileBlob == *newProfileBlob)
return;
Ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
// _LOG_DEBUG("Signing DONE!");
if(NULL == newEndorseCertificate)
return;
// _LOG_DEBUG("About to update");
m_contactStorage->updateSelfEndorseCertificate(newEndorseCertificate, identity);
publishSelfEndorseCertificateInDNS(newEndorseCertificate);
}
else
{
Ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
// _LOG_DEBUG("Signing DONE!");
if(NULL == newEndorseCertificate)
return;
// _LOG_DEBUG("About to Insert");
m_contactStorage->addSelfEndorseCertificate(newEndorseCertificate, identity);
publishSelfEndorseCertificateInDNS(newEndorseCertificate);
}
}
void
ContactManager::updateEndorseCertificate(const ndn::Name& identity, const ndn::Name& signerIdentity)
{
Ptr<Blob> oldEndorseCertificateBlob = m_contactStorage->getEndorseCertificate(identity);
Ptr<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identity, signerIdentity);
if(NULL != oldEndorseCertificateBlob)
{
Ptr<Data> plainData = Data::decodeFromWire(oldEndorseCertificateBlob);
EndorseCertificate oldEndorseCertificate(*plainData);
const Blob& oldEndorseContent = oldEndorseCertificate.content();
const Blob& newEndorseContent = newEndorseCertificate->content();
if(oldEndorseContent == newEndorseContent)
return;
}
else
{
if(NULL == newEndorseCertificate)
return;
}
m_contactStorage->addEndorseCertificate(newEndorseCertificate, identity);
publishEndorseCertificateInDNS(newEndorseCertificate, signerIdentity);
}
Ptr<EndorseCertificate>
ContactManager::generateEndorseCertificate(const Name& identity, const Name& signerIdentity)
{
Ptr<ContactItem> contact = getContact(identity);
if(contact == NULL)
return NULL;
Ptr<IdentityManager> identityManager = m_keychain->getIdentityManager();
Name signerKeyName = identityManager->getDefaultKeyNameForIdentity(signerIdentity);
Name signerCertName = identityManager->getDefaultCertificateNameByIdentity(signerIdentity);
vector<string> endorseList = m_contactStorage->getEndorseList(identity);
Ptr<EndorseCertificate> cert = Ptr<EndorseCertificate>(new EndorseCertificate(contact->getSelfEndorseCertificate(), signerKeyName, endorseList));
identityManager->signByCertificate(*cert, signerCertName);
return cert;
}
vector<Ptr<ContactItem> >
ContactManager::getContactItemList()
{ return m_contactStorage->getAllContacts(); }
Ptr<ContactItem>
ContactManager::getContact(const ndn::Name& contactNamespace)
{ return m_contactStorage->getContact(contactNamespace); }
Ptr<EndorseCertificate>
ContactManager::getSignedSelfEndorseCertificate(const Name& identity,
const Profile& profile)
{
Ptr<IdentityManager> identityManager = m_keychain->getIdentityManager();
Name certificateName = identityManager->getDefaultCertificateNameByIdentity(identity);
if(0 == certificateName.size())
return NULL;
Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(profile));
identityManager->signByCertificate(*profileData, certificateName);
Ptr<security::IdentityCertificate> signingCert = identityManager->getCertificate(certificateName);
if(NULL == signingCert)
return NULL;
Name signingKeyName = security::IdentityCertificate::certificateNameToPublicKeyName(signingCert->getName(), true);
Ptr<security::IdentityCertificate> kskCert;
if(signingKeyName.get(-1).toUri().substr(0,4) == string("dsk-"))
{
Ptr<const signature::Sha256WithRsa> dskCertSig = DynamicCast<const signature::Sha256WithRsa>(signingCert->getSignature());
// HACK! KSK certificate should be retrieved from network.
Name keyName = security::IdentityCertificate::certificateNameToPublicKeyName(dskCertSig->getKeyLocator().getKeyName());
Name kskCertName = identityManager->getPublicStorage()->getDefaultCertificateNameForKey(keyName);
kskCert = identityManager->getCertificate(kskCertName);
}
else
{
kskCert = signingCert;
}
if(NULL == kskCert)
return NULL;
vector<string> endorseList;
Profile::const_iterator it = profile.begin();
for(; it != profile.end(); it++)
endorseList.push_back(it->first);
Ptr<EndorseCertificate> selfEndorseCertificate = Ptr<EndorseCertificate>(new EndorseCertificate(*kskCert,
profileData,
endorseList));
identityManager->signByCertificate(*selfEndorseCertificate, kskCert->getName());
return selfEndorseCertificate;
}
void
ContactManager::onDnsSelfEndorseCertificateVerified(Ptr<Data> data, const Name& identity)
{
Ptr<Blob> dataContentBlob = Ptr<Blob>(new Blob(data->content().buf(), data->content().size()));
Ptr<Data> plainData = Data::decodeFromWire(dataContentBlob);
Ptr<EndorseCertificate> selfEndorseCertificate = Ptr<EndorseCertificate>(new EndorseCertificate(*plainData));
const security::Publickey& ksk = selfEndorseCertificate->getPublicKeyInfo();
if(security::PolicyManager::verifySignature(*plainData, ksk))
emit contactFetched (*selfEndorseCertificate);
else
emit contactFetchFailed (identity);
}
void
ContactManager::onDnsSelfEndorseCertificateUnverified(Ptr<Data> data, const Name& identity)
{ emit contactFetchFailed (identity); }
void
ContactManager::onDnsSelfEndorseCertificateTimeout(Ptr<Closure> closure, Ptr<Interest> interest, const Name& identity, int retry)
{ emit contactFetchFailed(identity); }
void
ContactManager::publishSelfEndorseCertificateInDNS(Ptr<EndorseCertificate> selfEndorseCertificate)
{
Ptr<Data> data = Ptr<Data>::Create();
Name keyName = selfEndorseCertificate->getPublicKeyName();
Name identity = keyName.getSubName(0, keyName.size()-1);
Name dnsName = identity;
dnsName.append("DNS").append("PROFILE").appendVersion();
data->setName(dnsName);
Ptr<Blob> blob = selfEndorseCertificate->encodeToWire();
Content content(blob->buf(), blob->size());
data->setContent(content);
m_keychain->signByIdentity(*data, identity);
m_dnsStorage->updateDnsSelfProfileData(*data, identity);
Ptr<Blob> dnsBlob = data->encodeToWire();
m_wrapper->putToNdnd(*dnsBlob);
}
void
ContactManager::publishEndorseCertificateInDNS(Ptr<EndorseCertificate> endorseCertificate, const Name& signerIdentity)
{
Ptr<Data> data = Ptr<Data>::Create();
Name keyName = endorseCertificate->getPublicKeyName();
Name endorsee = keyName.getSubName(0, keyName.size()-1);
Name dnsName = signerIdentity;
dnsName.append("DNS").append(endorsee).append("ENDORSEE").appendVersion();
data->setName(dnsName);
Ptr<Blob> blob = endorseCertificate->encodeToWire();
Content content(blob->buf(), blob->size());
data->setContent(content);
Name signCertName = m_keychain->getIdentityManager()->getDefaultCertificateNameByIdentity(signerIdentity);
m_keychain->getIdentityManager()->signByCertificate(*data, signCertName);
m_dnsStorage->updateDnsEndorseOthers(*data, signerIdentity, endorsee);
Ptr<Blob> dnsBlob = data->encodeToWire();
m_wrapper->putToNdnd(*dnsBlob);
}
void
ContactManager::publishEndorsedDataInDns(const Name& identity)
{
Ptr<Data> data = Ptr<Data>::Create();
Name dnsName = identity;
dnsName.append("DNS").append("ENDORSED").appendVersion();
data->setName(dnsName);
Ptr<vector<Blob> > collectEndorseList = m_contactStorage->getCollectEndorseList(identity);
Ptr<der::DerSequence> root = Ptr<der::DerSequence>::Create();
vector<Blob>::const_iterator it = collectEndorseList->begin();
for(; it != collectEndorseList->end(); it++)
{
Ptr<der::DerOctetString> entry = Ptr<der::DerOctetString>(new der::DerOctetString(*it));
root->addChild(entry);
}
blob_stream blobStream;
OutputIterator & start = reinterpret_cast<OutputIterator &> (blobStream);
root->encode(start);
Content content(blobStream.buf()->buf(), blobStream.buf()->size());
data->setContent(content);
Name signCertName = m_keychain->getIdentityManager()->getDefaultCertificateNameByIdentity(identity);
m_keychain->getIdentityManager()->signByCertificate(*data, signCertName);
m_dnsStorage->updateDnsOthersEndorse(*data, identity);
Ptr<Blob> dnsBlob = data->encodeToWire();
m_wrapper->putToNdnd(*dnsBlob);
}
#if WAF
#include "contact-manager.moc"
#include "contact-manager.cpp.moc"
#endif