blob: 7b07824daa70a5c027dfa457dc5c958de6bb9d54 [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/identity/basic-identity-storage.h>
#include <ndn.cxx/security/identity/osx-privatekey-storage.h>
#include <ndn.cxx/security/policy/simple-policy-manager.h>
#include <ndn.cxx/security/policy/identity-policy-rule.h>
#include <ndn.cxx/security/cache/ttl-certificate-cache.h>
#include <ndn.cxx/security/encryption/basic-encryption-manager.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<OSXPrivatekeyStorage> privateStorage = Ptr<OSXPrivatekeyStorage>::Create();
Ptr<IdentityManager> identityManager = Ptr<IdentityManager>(new IdentityManager(Ptr<BasicIdentityStorage>::Create(), privateStorage));
Ptr<TTLCertificateCache> certificateCache = Ptr<TTLCertificateCache>(new TTLCertificateCache());
Ptr<SimplePolicyManager> policyManager = Ptr<SimplePolicyManager>(new SimplePolicyManager(10, certificateCache));
Ptr<EncryptionManager> encryptionManager = Ptr<EncryptionManager>(new BasicEncryptionManager(privateStorage, "/tmp/encryption.db"));
Ptr<Keychain> keychain = Ptr<Keychain>(new Keychain(identityManager, policyManager, encryptionManager));
policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<DNS>]*)<DNS><PROFILE>",
"^([^<KEY>]*)<KEY>(<>*)<><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)));
ifstream is ("trust-anchor.data", ios::binary);
is.seekg (0, ios::end);
ifstream::pos_type size = is.tellg();
char * memblock = new char [size];
is.seekg (0, ios::beg);
is.read (memblock, size);
is.close();
Ptr<Blob> readBlob = Ptr<Blob>(new Blob(memblock, size));
Ptr<Data> readData = Data::decodeFromWire (readBlob);
Ptr<IdentityCertificate> anchor = Ptr<IdentityCertificate>(new IdentityCertificate(*readData));
policyManager->addTrustAnchor(anchor);
delete memblock;
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));
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::updateProfileData(const Name& identity)
{
// 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);
}
}
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(identity, profile));
identityManager->signByCertificate(*profileData, certificateName);
Ptr<security::IdentityCertificate> dskCert = identityManager->getCertificate(certificateName);
Ptr<const signature::Sha256WithRsa> dskCertSig = DynamicCast<const signature::Sha256WithRsa>(dskCert->getSignature());
// HACK! KSK certificate should be retrieved from network.
Ptr<security::IdentityCertificate> kskCert = identityManager->getCertificate(dskCertSig->getKeyLocator().getKeyName());
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,
kskCert->getNotBefore(),
kskCert->getNotAfter(),
profileData,
endorseList));
identityManager->signByCertificate(*selfEndorseCertificate, kskCert->getName());
return selfEndorseCertificate;
}
void
ContactManager::onDnsSelfEndorseCertificateVerified(Ptr<Data> data, const Name& identity)
{
const Blob& dataContentBlob = data->content();
boost::iostreams::stream
<boost::iostreams::array_source> is (dataContentBlob.buf(), dataContentBlob.size());
Ptr<Data> plainData = Data::decodeFromWire(is);
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)
{
if(retry > 0)
{
Ptr<Closure> newClosure = Ptr<Closure>(new Closure(closure->m_dataCallback,
boost::bind(&ContactManager::onDnsSelfEndorseCertificateTimeout,
this,
_1,
_2,
identity,
retry - 1),
closure->m_unverifiedCallback,
closure->m_stepCount)
);
m_wrapper->sendInterest(interest, newClosure);
}
else
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);
TimeInterval ti = time::NowUnixTimestamp();
ostringstream oss;
oss << ti.total_seconds();
Name dnsName = identity;
dnsName.append("DNS").append("PROFILE").append(oss.str());
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->putToCcnd(*dnsBlob);
}
#if WAF
#include "contact-manager.moc"
#include "contact-manager.cpp.moc"
#endif