blob: 27b78730eed9451c1d52f8dd6300922b3b5a22ba [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "pib-validator.hpp"
#include "encoding/pib-common.hpp"
#include "encoding/update-param.hpp"
#include <set>
#include <string>
namespace ndn {
namespace pib {
using std::set;
using std::string;
PibValidator::PibValidator(const PibDb& db, size_t maxCacheSize)
: m_db(db)
, m_isMgmtReady(false)
{
m_owner = m_db.getOwnerName();
m_mgmtCert = m_db.getMgmtCertificate();
if (!m_owner.empty() && m_mgmtCert != nullptr)
m_isMgmtReady = true;
m_mgmtChangeConnection =
const_cast<PibDb&>(m_db).mgmtCertificateChanged.connect([this] () {
m_owner = m_db.getOwnerName();
m_mgmtCert = m_db.getMgmtCertificate();
if (!m_owner.empty() && m_mgmtCert != nullptr)
m_isMgmtReady = true;
});
m_keyDeletedConnection =
const_cast<PibDb&>(m_db).keyDeleted.connect([this] (Name keyName) {
m_keyCache.erase(keyName);
});
}
PibValidator::~PibValidator()
{
}
void
PibValidator::checkPolicy(const Interest& interest,
int nSteps,
const OnInterestValidated& onValidated,
const OnInterestValidationFailed& onValidationFailed,
std::vector<shared_ptr<ValidationRequest>>& nextSteps)
{
if (!m_isMgmtReady)
return onValidationFailed(interest.shared_from_this(), "PibDb is not initialized");
const Name& interestName = interest.getName();
if (interestName.size() != SIGNED_PIB_INTEREST_SIZE) {
return onValidationFailed(interest.shared_from_this(),
"Interest is not signed: " + interest.getName().toUri());
}
// Check if the user exists in PIB
string user = interestName.get(OFFSET_USER).toUri();
if (user != m_owner)
return onValidationFailed(interest.shared_from_this(), "Wrong user: " + user);
// Verify signature
try {
Signature signature(interestName[OFFSET_SIG_INFO].blockFromValue(),
interestName[OFFSET_SIG_VALUE].blockFromValue());
// KeyLocator is required to contain the name of signing certificate (w/o version)
if (!signature.hasKeyLocator())
return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");
const KeyLocator& keyLocator = signature.getKeyLocator();
if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
return onValidationFailed(interest.shared_from_this(), "Key Locator is not a name");
// Check if PIB has the corresponding public key
shared_ptr<PublicKey> publicKey;
if (keyLocator.getName() == m_mgmtCert->getName().getPrefix(-1)) {
// the signing key is mgmt key.
publicKey = make_shared<PublicKey>(m_mgmtCert->getPublicKeyInfo());
}
else {
// the signing key is normal key.
Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocator.getName());
shared_ptr<PublicKey> key = m_keyCache.find(keyName);
if (key != nullptr) {
// the signing key is cached.
publicKey = key;
}
else {
// the signing key is not cached.
publicKey = m_db.getKey(keyName);
if (publicKey == nullptr) {
// the signing key does not exist in PIB.
return onValidationFailed(interest.shared_from_this(), "Public key is not trusted");
}
else {
// the signing key is retrieved from PIB.
m_keyCache.insert(keyName, publicKey);
}
}
}
if (verifySignature(interest, signature, *publicKey))
onValidated(interest.shared_from_this());
else
onValidationFailed(interest.shared_from_this(), "Cannot verify signature");
}
catch (KeyLocator::Error&) {
return onValidationFailed(interest.shared_from_this(),
"No valid KeyLocator");
}
catch (Signature::Error&) {
return onValidationFailed(interest.shared_from_this(),
"No valid signature");
}
catch (IdentityCertificate::Error&) {
return onValidationFailed(interest.shared_from_this(),
"Cannot determine the signing key");
}
catch (tlv::Error&) {
return onValidationFailed(interest.shared_from_this(),
"Cannot decode signature");
}
}
void
PibValidator::checkPolicy(const Data& data,
int nSteps,
const OnDataValidated& onValidated,
const OnDataValidationFailed& onValidationFailed,
std::vector<shared_ptr<ValidationRequest>>& nextSteps)
{
// Pib does not express any interest, therefor should not validate any data.
onValidationFailed(data.shared_from_this(),
"PibValidator should not receive data packet");
}
} // namespace pib
} // namespace ndn