blob: 0f4db3e35d6482e1a37180ad5f88ea44114fbbf9 [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 "sync-intro-certificate.h"
#include "sync-logging.h"
#include <ndn-cpp-dev/security/verifier.hpp>
#include <ndn-cpp-dev/security/signature-sha256-with-rsa.hpp>
#include "sec-policy-sync.h"
using namespace ndn;
using namespace ndn::ptr_lib;
using namespace std;
INIT_LOGGER("SecPolicySync");
SecPolicySync::SecPolicySync(const Name& signingIdentity,
const Name& signingCertificateName,
const Name& syncPrefix,
shared_ptr<Face> face,
int stepLimit)
: m_signingIdentity(signingIdentity)
, m_signingCertificateName(signingCertificateName.getPrefix(signingCertificateName.size()-1))
, m_syncPrefix(syncPrefix)
, m_stepLimit(stepLimit)
, m_keyChain(new KeyChain())
{
m_introCertPrefix = syncPrefix;
m_introCertPrefix.append("WOT");
m_syncDataPolicy = make_shared<SecRuleRelative>("^[^<%F0\\.>]*<%F0\\.>([^<chronos>]*)<chronos><>",
"^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$",
"==", "\\1", "\\1", true);
}
SecPolicySync::~SecPolicySync()
{}
bool
SecPolicySync::skipVerifyAndTrust (const Data& data)
{ return false; }
bool
SecPolicySync::requireVerify (const Data& data)
{ return true; }
shared_ptr<ValidationRequest>
SecPolicySync::checkVerificationPolicy(const shared_ptr<Data>& data,
int stepCount,
const OnVerified& onVerified,
const OnVerifyFailed& onVerifyFailed)
{
if(stepCount > m_stepLimit)
{
onVerifyFailed(data);
return shared_ptr<ValidationRequest>();
}
try{
SignatureSha256WithRsa sig(data->getSignature());
const Name& keyLocatorName = sig.getKeyLocator().getName();
// if data is intro cert
if(m_introCertPrefix.isPrefixOf(data->getName()))
{
Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
map<Name, PublicKey>::const_iterator it = m_trustedIntroducers.find(keyName);
if(m_trustedIntroducers.end() != it)
{
if(Verifier::verifySignature(*data, sig, it->second))
onVerified(data);
else
onVerifyFailed(data);
return shared_ptr<ValidationRequest>();
}
else
return prepareRequest(keyName, true, data, stepCount, onVerified, onVerifyFailed);
}
// if data is diff data or sync data
if(m_syncPrefix.isPrefixOf(data->getName()) || m_syncDataPolicy->satisfy(*data))
{
Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
map<Name, PublicKey>::const_iterator it = m_trustedIntroducers.find(keyName);
if(m_trustedIntroducers.end() != it)
{
if(Verifier::verifySignature(*data, sig, it->second))
onVerified(data);
else
onVerifyFailed(data);
return shared_ptr<ValidationRequest>();
}
it = m_trustedProducers.find(keyName);
if(m_trustedProducers.end() != it)
{
if(Verifier::verifySignature(*data, sig, it->second))
onVerified(data);
else
onVerifyFailed(data);
return shared_ptr<ValidationRequest>();
}
return prepareRequest(keyName, false, data, stepCount, onVerified, onVerifyFailed);
}
}catch(SignatureSha256WithRsa::Error &e){
_LOG_DEBUG("SecPolicySync Error: " << e.what());
onVerifyFailed(data);
return shared_ptr<ValidationRequest>();
}catch(KeyLocator::Error &e){
_LOG_DEBUG("SecPolicySync Error: " << e.what());
onVerifyFailed(data);
return shared_ptr<ValidationRequest>();
}
onVerifyFailed(data);
return shared_ptr<ValidationRequest>();
}
bool
SecPolicySync::checkSigningPolicy(const Name& dataName,
const Name& certificateName)
{
return true;
}
Name
SecPolicySync::inferSigningIdentity(const ndn::Name& dataName)
{ return m_signingIdentity; }
void
SecPolicySync::addTrustAnchor(const IdentityCertificate& identityCertificate, bool isIntroducer)
{
Name publicKeyName = identityCertificate.getPublicKeyName();
_LOG_DEBUG("Add intro/producer: " << publicKeyName);
if(isIntroducer)
m_trustedIntroducers[publicKeyName] = identityCertificate.getPublicKeyInfo();
else
m_trustedProducers[publicKeyName] = identityCertificate.getPublicKeyInfo();
}
void
SecPolicySync::addSyncDataRule(const Name& prefix,
const IdentityCertificate& identityCertificate,
bool isIntroducer)
{ addTrustAnchor(identityCertificate, isIntroducer); }
shared_ptr<const vector<Name> >
SecPolicySync::getAllIntroducerName()
{
shared_ptr<vector<Name> > nameList = make_shared<vector<Name> >();
map<Name, PublicKey>::iterator it = m_trustedIntroducers.begin();
for(; it != m_trustedIntroducers.end(); it++)
nameList->push_back(it->first);
return nameList;
}
shared_ptr<ValidationRequest>
SecPolicySync::prepareRequest(const Name& keyName,
bool forIntroducer,
shared_ptr<Data> data,
const int & stepCount,
const OnVerified& onVerified,
const OnVerifyFailed& onVerifyFailed)
{
Name interestPrefix = m_syncPrefix;
interestPrefix.append("WOT").append(keyName.wireEncode()).append("INTRO-CERT");
shared_ptr<const vector<Name> > nameList = getAllIntroducerName();
if(0 == nameList->size())
{
onVerifyFailed(data);
return shared_ptr<ValidationRequest>();
}
Name interestName = interestPrefix;
interestName.append(nameList->at(0).wireEncode());
if(forIntroducer)
interestName.append("INTRODUCER");
shared_ptr<ndn::Interest> interest = make_shared<ndn::Interest>(interestName);
OnVerified introCertVerified = func_lib::bind(&SecPolicySync::onIntroCertVerified,
this,
_1,
forIntroducer,
data,
onVerified,
onVerifyFailed);
OnVerifyFailed introCertVerifyFailed = func_lib::bind(&SecPolicySync::onIntroCertVerifyFailed,
this,
_1,
interestPrefix,
forIntroducer,
nameList,
1,
data,
onVerified,
onVerifyFailed);
shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(interest,
introCertVerified,
introCertVerifyFailed,
1,
m_stepLimit-1);
return nextStep;
}
void
SecPolicySync::OnIntroCertInterest(const shared_ptr<const Name>& prefix,
const shared_ptr<const ndn::Interest>& interest,
Transport& transport,
uint64_t registeredPrefixId)
{
map<Name, Data>::const_iterator it = m_introCert.find(*prefix);
if(m_introCert.end() != it)
m_face->put(it->second);
}
void
SecPolicySync::OnIntroCertRegisterFailed(const shared_ptr<const Name>& prefix)
{
}
void
SecPolicySync::onIntroCertVerified(const shared_ptr<Data>& introCertificateData,
bool forIntroducer,
shared_ptr<Data> originalData,
const OnVerified& onVerified,
const OnVerifyFailed& onVerifyFailed)
{
shared_ptr<SyncIntroCertificate> introCertificate = make_shared<SyncIntroCertificate>(*introCertificateData);
Name subjectKeyName = introCertificate->getPublicKeyName();
if(forIntroducer)
{
//Add the intro cert subject as trusted introducer.
m_trustedIntroducers[subjectKeyName] = introCertificate->getPublicKeyInfo();
//Generate another intro cert for the cert subject.
SyncIntroCertificate syncIntroCertificate(m_syncPrefix,
subjectKeyName,
m_keyChain->getDefaultKeyNameForIdentity(m_signingIdentity),
introCertificate->getNotBefore(),
introCertificate->getNotAfter(),
introCertificate->getPublicKeyInfo(),
SyncIntroCertificate::INTRODUCER);
m_keyChain->signByIdentity(syncIntroCertificate, m_signingIdentity);
m_face->put(syncIntroCertificate);
// Name prefix = syncIntroCertificate.getName().getPrefix(syncIntroCertificate.getName().size()-1);
// map<string, Data>::const_iterator it = m_introCert.find(prefix);
// if(m_introCert.end() != it)
// {
// it->second = syncIntroCertificate;
// }
// else
// {
// m_introCert.insert(pair <Name, Data> (prefix, syncIntroCertificate));
// m_face->registerPrefix(prefix,
// boost::bind(&SecPolicySync::onIntroCertInterest, this, _1, _2, _3, _4),
// boost::bind(&SecPolicySync::onIntroCertRegisterFailed, this, _1));
// }
}
else
{
//Add the intro cert subject as trusted producer.
m_trustedProducers[subjectKeyName] = introCertificate->getPublicKeyInfo();
//Generate another intro cert for the cert subject.
SyncIntroCertificate syncIntroCertificate(m_syncPrefix,
subjectKeyName,
m_keyChain->getDefaultKeyNameForIdentity(m_signingIdentity),
introCertificate->getNotBefore(),
introCertificate->getNotAfter(),
introCertificate->getPublicKeyInfo(),
SyncIntroCertificate::PRODUCER);
m_keyChain->signByIdentity(syncIntroCertificate, m_signingIdentity);
m_face->put(syncIntroCertificate);
// Name prefix = syncIntroCertificate.getName().getPrefix(syncIntroCertificate.getName().size()-1);
// map<string, Data>::const_iterator it = m_introCert.find(prefix);
// if(m_introCert.end() != it)
// {
// it->second = syncIntroCertificate;
// }
// else
// {
// m_introCert.insert(pair <Name, Data> (prefix, syncIntroCertificate));
// m_face->registerPrefix(prefix,
// boost::bind(&SecPolicySync::onIntroCertInterest, this, _1, _2, _3, _4),
// boost::bind(&SecPolicySync::onIntroCertRegisterFailed, this, _1));
// }
}
try{
SignatureSha256WithRsa sig(originalData->getSignature());
if(Verifier::verifySignature(*originalData, sig, introCertificate->getPublicKeyInfo()))
onVerified(originalData);
else
onVerifyFailed(originalData);
}catch(SignatureSha256WithRsa::Error &e){
onVerifyFailed(originalData);
}catch(KeyLocator::Error &e){
onVerifyFailed(originalData);
}
}
void
SecPolicySync::onIntroCertVerifyFailed(const shared_ptr<Data>& introCertificateData,
Name interestPrefix,
bool forIntroducer,
shared_ptr<const vector<Name> > introNameList,
int nextIntroducerIndex,
shared_ptr<Data> originalData,
const OnVerified& onVerified,
const OnVerifyFailed& onVerifyFailed)
{
Name interestName = interestPrefix;
if(nextIntroducerIndex < introNameList->size())
interestName.append(introNameList->at(nextIntroducerIndex).wireEncode());
else
onVerifyFailed(originalData);
if(forIntroducer)
interestName.append("INTRODUCER");
ndn::Interest interest(interestName);
OnVerified introCertVerified = func_lib::bind(&SecPolicySync::onIntroCertVerified,
this,
_1,
forIntroducer,
originalData,
onVerified,
onVerifyFailed);
OnVerifyFailed introCertVerifyFailed = func_lib::bind(&SecPolicySync::onIntroCertVerifyFailed,
this,
_1,
interestPrefix,
forIntroducer,
introNameList,
nextIntroducerIndex + 1,
originalData,
onVerified,
onVerifyFailed);
m_face->expressInterest(interest,
func_lib::bind(&SecPolicySync::onIntroCertData,
this,
_1,
_2,
m_stepLimit-1,
introCertVerified,
introCertVerifyFailed),
func_lib::bind(&SecPolicySync::onIntroCertTimeout,
this,
_1,
1,
m_stepLimit-1,
introCertVerified,
introCertVerifyFailed)
);
}
void
SecPolicySync::onIntroCertData(const shared_ptr<const ndn::Interest> &interest,
const shared_ptr<Data>& introCertificateData,
int stepCount,
const OnVerified& introCertVerified,
const OnVerifyFailed& introCertVerifyFailed)
{
shared_ptr<ValidationRequest> nextStep = checkVerificationPolicy(introCertificateData, stepCount, introCertVerified, introCertVerifyFailed);
if (nextStep)
m_face->expressInterest(*nextStep->interest_,
func_lib::bind(&SecPolicySync::onIntroCertData,
this,
_1,
_2,
nextStep->stepCount_,
nextStep->onVerified_,
nextStep->onVerifyFailed_),
func_lib::bind(&SecPolicySync::onIntroCertTimeout,
this,
_1,
nextStep->retry_,
nextStep->stepCount_,
nextStep->onVerified_,
nextStep->onVerifyFailed_)
);
}
void
SecPolicySync::onIntroCertTimeout(const shared_ptr<const ndn::Interest>& interest,
int retry,
int stepCount,
const OnVerified& introCertVerified,
const OnVerifyFailed& introCertVerifyFailed)
{
if(retry > 0)
m_face->expressInterest(*interest,
func_lib::bind(&SecPolicySync::onIntroCertData,
this,
_1,
_2,
stepCount,
introCertVerified,
introCertVerifyFailed),
func_lib::bind(&SecPolicySync::onIntroCertTimeout,
this,
_1,
retry - 1,
stepCount,
introCertVerified,
introCertVerifyFailed)
);
else
introCertVerifyFailed(shared_ptr<Data>());
}