blob: b225c531d9f32bdbc9a6b352122fd9900e26653b [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library 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 Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#ifndef NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
#define NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
#include "ndn-cxx/security/validator.hpp"
#include "ndn-cxx/security/certificate-fetcher-from-network.hpp"
#include "ndn-cxx/util/dummy-client-face.hpp"
#include "tests/boost-test.hpp"
#include "tests/unit/io-key-chain-fixture.hpp"
#include <boost/lexical_cast.hpp>
namespace ndn {
namespace security {
inline namespace v2 {
namespace tests {
class ValidatorFixtureBase : public ndn::tests::IoKeyChainFixture
{
protected:
ValidatorFixtureBase();
void
mockNetworkOperations();
/** \brief undo clock advancement of mockNetworkOperations()
*/
void
rewindClockAfterValidation()
{
m_systemClock->advance(s_mockPeriod * s_mockTimes * -1);
}
/**
* @brief Issues a certificate for @p subIdentityName signed by @p issuer
*
* If the identity does not exist, it is created.
* A new key is generated as the default key for the identity.
* A default certificate for the key is signed by the issuer using its default certificate.
*
* @return The sub-identity
*/
Identity
addSubCertificate(const Name& subIdentityName, const Identity& issuer);
protected:
util::DummyClientFace face{m_io, {true, true}};
std::function<void(const Interest&)> processInterest;
CertificateCache cache{100_days};
ValidationError lastError{ValidationError::NO_ERROR};
private:
const static time::milliseconds s_mockPeriod;
const static int s_mockTimes;
};
template<class ValidationPolicyT, class CertificateFetcherT = CertificateFetcherFromNetwork>
class ValidatorFixture : public ValidatorFixtureBase
{
protected:
ValidatorFixture()
: validator(make_unique<ValidationPolicyT>(), make_unique<CertificateFetcherT>(face))
, policy(static_cast<ValidationPolicyT&>(validator.getPolicy()))
{
}
template<class Packet>
void
validate(const Packet& packet, const std::string& msg, bool expectSuccess, int line)
{
std::string detailedInfo = msg + " on line " + to_string(line);
size_t nCallbacks = 0;
this->validator.validate(packet,
[&] (const Packet&) {
++nCallbacks;
BOOST_CHECK_MESSAGE(expectSuccess,
(expectSuccess ? "OK: " : "FAILED: ") + detailedInfo);
},
[&] (const Packet&, const ValidationError& error) {
lastError = error;
++nCallbacks;
BOOST_CHECK_MESSAGE(!expectSuccess,
(!expectSuccess ? "OK: " : "FAILED: ") + detailedInfo +
(expectSuccess ? " (" + boost::lexical_cast<std::string>(error) + ")" : ""));
});
mockNetworkOperations();
BOOST_CHECK_EQUAL(nCallbacks, 1);
}
protected:
Validator validator;
ValidationPolicyT& policy;
};
template<class ValidationPolicyT, class CertificateFetcherT = CertificateFetcherFromNetwork>
class HierarchicalValidatorFixture : public ValidatorFixture<ValidationPolicyT, CertificateFetcherT>
{
protected:
HierarchicalValidatorFixture()
{
identity = this->m_keyChain.createIdentity("/Security/ValidatorFixture");
subIdentity = this->addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
subSelfSignedIdentity = this->m_keyChain.createIdentity("/Security/ValidatorFixture/Sub1/Sub2");
otherIdentity = this->m_keyChain.createIdentity("/Security/OtherIdentity");
this->validator.loadAnchor("", Certificate(identity.getDefaultKey().getDefaultCertificate()));
this->cache.insert(identity.getDefaultKey().getDefaultCertificate());
this->cache.insert(subIdentity.getDefaultKey().getDefaultCertificate());
this->cache.insert(subSelfSignedIdentity.getDefaultKey().getDefaultCertificate());
this->cache.insert(otherIdentity.getDefaultKey().getDefaultCertificate());
}
protected:
Identity identity;
Identity subIdentity;
Identity subSelfSignedIdentity;
Identity otherIdentity;
};
#define VALIDATE_SUCCESS(packet, message) this->validate(packet, message, true, __LINE__)
#define VALIDATE_FAILURE(packet, message) this->validate(packet, message, false, __LINE__)
class DummyValidationState : public ValidationState
{
public:
~DummyValidationState() override
{
m_outcome = false;
}
void
fail(const ValidationError&) override
{
m_outcome = false;
}
private:
void
verifyOriginalPacket(const optional<Certificate>&) override
{
// do nothing
}
void
bypassValidation() override
{
// do nothing
}
};
struct DataPkt
{
static constexpr uint32_t
getType()
{
return tlv::Data;
}
static Name
makeName(Name name, KeyChain&)
{
return name;
}
static Data
makePacket(const Name& name)
{
return Data(name);
}
static shared_ptr<ValidationState>
makeState()
{
return make_shared<DummyValidationState>();
}
};
struct InterestV02Pkt
{
static constexpr uint32_t
getType()
{
return tlv::Interest;
}
static Name
makeName(Name name, KeyChain& keyChain);
static Interest
makePacket(const Name& name)
{
return Interest(name);
}
static shared_ptr<ValidationState>
makeState()
{
auto state = make_shared<DummyValidationState>();
state->setTag(make_shared<SignedInterestFormatTag>(SignedInterestFormat::V02));
return state;
}
};
struct InterestV03Pkt
{
static constexpr uint32_t
getType()
{
return tlv::Interest;
}
static Name
makeName(Name name, KeyChain& keyChain);
static Interest
makePacket(const Name& name)
{
return Interest(name);
}
static shared_ptr<ValidationState>
makeState()
{
auto state = make_shared<DummyValidationState>();
state->setTag(make_shared<SignedInterestFormatTag>(SignedInterestFormat::V03));
return state;
}
};
} // namespace tests
} // inline namespace v2
} // namespace security
} // namespace ndn
#endif // NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP