| /* -*- 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-policy-manager.h" |
| |
| #include "sync-intro-certificate.h" |
| #include "sync-logging.h" |
| |
| using namespace ndn; |
| using namespace ndn::security; |
| using namespace std; |
| |
| INIT_LOGGER("SyncPolicyManager"); |
| |
| SyncPolicyManager::SyncPolicyManager(const Name& signingIdentity, |
| const Name& signingCertificateName, |
| const Name& syncPrefix, |
| int stepLimit) |
| : m_signingIdentity(signingIdentity) |
| , m_signingCertificateName(signingCertificateName.getPrefix(signingCertificateName.size()-1)) |
| , m_syncPrefix(syncPrefix) |
| , m_stepLimit(stepLimit) |
| { |
| Name wotPrefix = syncPrefix; |
| wotPrefix.append("WOT"); |
| m_syncPrefixRegex = Regex::fromName(syncPrefix); |
| m_wotPrefixRegex = Regex::fromName(wotPrefix); |
| m_chatDataPolicy = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^[^<FH>]*<FH>([^<chronos>]*)<chronos><>", |
| "^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$", |
| "==", "\\1", "\\1", true)); |
| } |
| |
| SyncPolicyManager::~SyncPolicyManager() |
| {} |
| |
| bool |
| SyncPolicyManager::skipVerifyAndTrust (const Data& data) |
| { return false; } |
| |
| bool |
| SyncPolicyManager::requireVerify (const Data& data) |
| { return true; } |
| |
| Ptr<ValidationRequest> |
| SyncPolicyManager::checkVerificationPolicy(Ptr<Data> data, |
| const int& stepCount, |
| const DataCallback& verifiedCallback, |
| const UnverifiedCallback& unverifiedCallback) |
| { |
| // #ifdef _DEBUG |
| // _LOG_DEBUG("checkVerificationPolicy"); |
| // verifiedCallback(data); |
| // return NULL; |
| // #else |
| //TODO: |
| if(stepCount > m_stepLimit) |
| { |
| unverifiedCallback(data); |
| return NULL; |
| } |
| |
| Ptr<const signature::Sha256WithRsa> sha256sig = DynamicCast<const signature::Sha256WithRsa> (data->getSignature()); |
| if(KeyLocator::KEYNAME != sha256sig->getKeyLocator().getType()) |
| { |
| unverifiedCallback(data); |
| return NULL; |
| } |
| |
| const Name& keyLocatorName = sha256sig->getKeyLocator().getKeyName(); |
| _LOG_DEBUG("data name: " << data->getName()); |
| _LOG_DEBUG("signer name: " << keyLocatorName); |
| |
| // if data is intro cert |
| if(m_wotPrefixRegex->match(data->getName())) |
| { |
| _LOG_DEBUG("Intro Cert"); |
| Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName); |
| map<Name, Publickey>::const_iterator it = m_trustedIntroducers.find(keyName); |
| if(m_trustedIntroducers.end() != it) |
| { |
| if(verifySignature(*data, it->second)) |
| verifiedCallback(data); |
| else |
| unverifiedCallback(data); |
| return NULL; |
| } |
| else |
| return prepareRequest(keyName, true, data, stepCount, verifiedCallback, unverifiedCallback); |
| } |
| |
| // if data is sync data or chat data |
| if(m_syncPrefixRegex->match(data->getName()) || m_chatDataPolicy->satisfy(*data)) |
| { |
| _LOG_DEBUG("Sync/Chat Data"); |
| Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName); |
| _LOG_DEBUG("keyName: " << keyName.toUri()); |
| |
| map<Name, Publickey>::const_iterator it = m_trustedIntroducers.find(keyName); |
| if(m_trustedIntroducers.end() != it) |
| { |
| _LOG_DEBUG("Find trusted introducer!"); |
| if(verifySignature(*data, it->second)) |
| verifiedCallback(data); |
| else |
| unverifiedCallback(data); |
| return NULL; |
| } |
| |
| it = m_trustedProducers.find(keyName); |
| if(m_trustedProducers.end() != it) |
| { |
| _LOG_DEBUG("Find trusted producer!"); |
| if(verifySignature(*data, it->second)) |
| verifiedCallback(data); |
| else |
| unverifiedCallback(data); |
| return NULL; |
| } |
| |
| _LOG_DEBUG("Did not find any trusted one!"); |
| return prepareRequest(keyName, false, data, stepCount, verifiedCallback, unverifiedCallback); |
| } |
| |
| unverifiedCallback(data); |
| return NULL; |
| // #endif |
| } |
| |
| bool |
| SyncPolicyManager::checkSigningPolicy(const Name& dataName, |
| const Name& certificateName) |
| { |
| |
| return true; |
| |
| // #ifdef _DEBUG |
| // _LOG_DEBUG("checkSigningPolicy"); |
| // return true; |
| // #else |
| // return (m_syncPrefixRegex->match(dataName) && certificateName.getPrefix(certificateName.size()-1) == m_signingCertificateName) ? true : false; |
| // #endif |
| } |
| |
| Name |
| SyncPolicyManager::inferSigningIdentity(const ndn::Name& dataName) |
| { return m_signingIdentity; } |
| |
| void |
| SyncPolicyManager::addTrustAnchor(const IdentityCertificate& identityCertificate, bool isIntroducer) |
| { |
| _LOG_DEBUG("Add intro/producer: " << identityCertificate.getPublicKeyName()); |
| if(isIntroducer) |
| m_trustedIntroducers.insert(pair <Name, Publickey > (identityCertificate.getPublicKeyName(), identityCertificate.getPublicKeyInfo())); |
| else |
| m_trustedProducers.insert(pair <Name, Publickey > (identityCertificate.getPublicKeyName(), identityCertificate.getPublicKeyInfo())); |
| } |
| |
| void |
| SyncPolicyManager::addChatDataRule(const Name& prefix, |
| const IdentityCertificate& identityCertificate, |
| bool isIntroducer) |
| { |
| // Name dataPrefix = prefix; |
| // dataPrefix.append("chronos").append(m_syncPrefix.get(-1)); |
| // Ptr<Regex> dataRegex = Regex::fromName(prefix); |
| // Name certName = identityCertificate.getName(); |
| // Name signerName = certName.getPrefix(certName.size()-1); |
| // Ptr<Regex> signerRegex = Regex::fromName(signerName, true); |
| |
| // SpecificPolicyRule rule(dataRegex, signerRegex); |
| // map<Name, SpecificPolicyRule>::iterator it = m_chatDataRules.find(dataPrefix); |
| // if(it != m_chatDataRules.end()) |
| // it->second = rule; |
| // else |
| // m_chatDataRules.insert(pair <Name, SpecificPolicyRule > (dataPrefix, rule)); |
| |
| addTrustAnchor(identityCertificate, isIntroducer); |
| } |
| |
| |
| Ptr<const vector<Name> > |
| SyncPolicyManager::getAllIntroducerName() |
| { |
| Ptr<vector<Name> > nameList = Ptr<vector<Name> >(new vector<Name>); |
| |
| map<Name, Publickey>::iterator it = m_trustedIntroducers.begin(); |
| for(; it != m_trustedIntroducers.end(); it++) |
| nameList->push_back(it->first); |
| |
| return nameList; |
| } |
| |
| Ptr<ValidationRequest> |
| SyncPolicyManager::prepareRequest(const Name& keyName, |
| bool forIntroducer, |
| Ptr<Data> data, |
| const int & stepCount, |
| const DataCallback& verifiedCallback, |
| const UnverifiedCallback& unverifiedCallback) |
| { |
| Ptr<Name> interestPrefixName = Ptr<Name>(new Name(m_syncPrefix)); |
| interestPrefixName->append("WOT").append(keyName).append("INTRO-CERT"); |
| |
| Ptr<const std::vector<ndn::Name> > nameList = getAllIntroducerName(); |
| if(0 == nameList->size()) |
| { |
| unverifiedCallback(data); |
| return NULL; |
| } |
| |
| Name interestName = *interestPrefixName; |
| interestName.append(nameList->at(0)); |
| |
| if(forIntroducer) |
| interestName.append("INTRODUCER"); |
| |
| Ptr<Interest> interest = Ptr<Interest>(new Interest(interestName)); |
| _LOG_DEBUG("send interest for intro cert: " << interest->getName()); |
| interest->setChildSelector(Interest::CHILD_RIGHT); |
| |
| DataCallback requestedCertVerifiedCallback = boost::bind(&SyncPolicyManager::onIntroCertVerified, |
| this, |
| _1, |
| forIntroducer, |
| data, |
| verifiedCallback, |
| unverifiedCallback); |
| |
| UnverifiedCallback requestedCertUnverifiedCallback = boost::bind(&SyncPolicyManager::onIntroCertUnverified, |
| this, |
| _1, |
| interestPrefixName, |
| forIntroducer, |
| nameList, |
| 1, |
| data, |
| verifiedCallback, |
| unverifiedCallback); |
| |
| |
| Ptr<ValidationRequest> nextStep = Ptr<ValidationRequest>(new ValidationRequest(interest, |
| requestedCertVerifiedCallback, |
| requestedCertUnverifiedCallback, |
| 1, |
| m_stepLimit-1) |
| ); |
| return nextStep; |
| } |
| |
| void |
| SyncPolicyManager::onIntroCertVerified(Ptr<Data> introCertificateData, |
| bool forIntroducer, |
| Ptr<Data> originalData, |
| const DataCallback& verifiedCallback, |
| const UnverifiedCallback& unverifiedCallback) |
| { |
| Ptr<SyncIntroCertificate> introCertificate = Ptr<SyncIntroCertificate>(new SyncIntroCertificate(*introCertificateData)); |
| if(forIntroducer) |
| m_trustedIntroducers.insert(pair <Name, Publickey > (introCertificate->getPublicKeyName(), introCertificate->getPublicKeyInfo())); |
| else |
| m_trustedProducers.insert(pair <Name, Publickey > (introCertificate->getPublicKeyName(), introCertificate->getPublicKeyInfo())); |
| |
| if(verifySignature(*originalData, introCertificate->getPublicKeyInfo())) |
| verifiedCallback(originalData); |
| else |
| unverifiedCallback(originalData); |
| } |
| |
| void |
| SyncPolicyManager::onIntroCertUnverified(Ptr<Data> introCertificateData, |
| Ptr<Name> interestPrefixName, |
| bool forIntroducer, |
| Ptr<const std::vector<ndn::Name> > introNameList, |
| const int& nextIntroducerIndex, |
| Ptr<Data> originalData, |
| const DataCallback& verifiedCallback, |
| const UnverifiedCallback& unverifiedCallback) |
| { |
| Name interestName = *interestPrefixName; |
| if(nextIntroducerIndex < introNameList->size()) |
| interestName.append(introNameList->at(nextIntroducerIndex)); |
| else |
| unverifiedCallback(originalData); |
| |
| if(forIntroducer) |
| interestName.append("INTRODUCER"); |
| |
| Ptr<Interest> interest = Ptr<Interest>(new Interest(interestName)); |
| interest->setChildSelector(Interest::CHILD_RIGHT); |
| |
| DataCallback requestedCertVerifiedCallback = boost::bind(&SyncPolicyManager::onIntroCertVerified, |
| this, |
| _1, |
| forIntroducer, |
| originalData, |
| verifiedCallback, |
| unverifiedCallback); |
| |
| UnverifiedCallback requestedCertUnverifiedCallback = boost::bind(&SyncPolicyManager::onIntroCertUnverified, |
| this, |
| _1, |
| interestPrefixName, |
| forIntroducer, |
| introNameList, |
| nextIntroducerIndex + 1, |
| originalData, |
| verifiedCallback, |
| unverifiedCallback); |
| |
| TimeoutCallback requestedCertTimeoutCallback = boost::bind(&SyncPolicyManager::onIntroCertTimeOut, |
| this, |
| _1, |
| _2, |
| 1, |
| requestedCertUnverifiedCallback, |
| originalData); |
| |
| Ptr<Closure> closure = Ptr<Closure> (new Closure(requestedCertVerifiedCallback, |
| requestedCertTimeoutCallback, |
| requestedCertUnverifiedCallback, |
| m_stepLimit-1) |
| ); |
| |
| m_handler->sendInterest(interest, closure); |
| } |
| |
| void |
| SyncPolicyManager::onIntroCertTimeOut(Ptr<Closure> closure, |
| Ptr<Interest> interest, |
| int retry, |
| const UnverifiedCallback& unverifiedCallback, |
| Ptr<Data> data) |
| { |
| if(retry > 0) |
| { |
| Ptr<Closure> newClosure = Ptr<Closure>(new Closure(closure->m_dataCallback, |
| boost::bind(&SyncPolicyManager::onIntroCertTimeOut, |
| this, |
| _1, |
| _2, |
| retry - 1, |
| unverifiedCallback, |
| data), |
| closure->m_unverifiedCallback, |
| closure->m_stepCount) |
| ); |
| m_handler->sendInterest(interest, newClosure); |
| } |
| else |
| unverifiedCallback(data); |
| } |