29 #include <ndn-cxx/security/certificate-fetcher-offline.hpp>
30 #include <ndn-cxx/security/certificate-request.hpp>
31 #include <ndn-cxx/security/validation-policy.hpp>
32 #include <ndn-cxx/security/validation-policy-accept-all.hpp>
33 #include <ndn-cxx/security/validation-policy-command-interest.hpp>
34 #include <ndn-cxx/tag.hpp>
35 #include <ndn-cxx/util/io.hpp>
39 namespace security = ndn::security;
55 static std::optional<std::string>
58 auto signerTag = interest.getTag<
SignerTag>();
59 if (signerTag ==
nullptr) {
63 return signerTag->get().toUri();
70 class CommandAuthenticatorValidationPolicy final :
public security::ValidationPolicy
74 checkPolicy(
const Interest& interest,
const shared_ptr<security::ValidationState>& state,
75 const ValidationContinuation& continueValidation)
final
77 auto sigInfo = getSignatureInfo(interest, *state);
78 if (!state->getOutcome()) {
81 Name klName = getKeyLocatorName(sigInfo, *state);
82 if (!state->getOutcome()) {
89 auto state1 = std::dynamic_pointer_cast<security::InterestValidationState>(state);
90 state1->getOriginalInterest().setTag(make_shared<SignerTag>(klName));
92 continueValidation(make_shared<security::CertificateRequest>(klName), state);
96 checkPolicy(
const Data&,
const shared_ptr<security::ValidationState>&,
97 const ValidationContinuation&)
final
101 BOOST_ASSERT_MSG(
false,
"Data should not be passed to this policy");
105 shared_ptr<CommandAuthenticator>
111 CommandAuthenticator::CommandAuthenticator() =
default;
117 processConfig(std::forward<decltype(args)>(args)...);
122 CommandAuthenticator::processConfig(
const ConfigSection& section,
bool isDryRun,
const std::string& filename)
126 for (
auto& kv : m_validators) {
127 kv.second = make_shared<security::Validator>(
128 make_unique<security::ValidationPolicyCommandInterest>(make_unique<CommandAuthenticatorValidationPolicy>()),
129 make_unique<security::CertificateFetcherOffline>());
133 if (section.empty()) {
134 NDN_THROW(ConfigFile::Error(
"'authorize' is missing under 'authorizations'"));
137 int authSectionIndex = 0;
138 for (
const auto& [sectionName, authSection] : section) {
139 if (sectionName !=
"authorize") {
140 NDN_THROW(ConfigFile::Error(
"'" + sectionName +
"' section is not permitted under 'authorizations'"));
143 std::string certfile;
145 certfile = authSection.get<std::string>(
"certfile");
147 catch (
const boost::property_tree::ptree_error&) {
148 NDN_THROW(ConfigFile::Error(
"'certfile' is missing under authorize[" +
149 std::to_string(authSectionIndex) +
"]"));
153 shared_ptr<security::Certificate> cert;
154 if (certfile ==
"any") {
156 NFD_LOG_WARN(
"'certfile any' is intended for demo purposes only and "
157 "SHOULD NOT be used in production environments");
160 auto certfilePath = std::filesystem::absolute(filename).parent_path() / certfile;
161 certfilePath = certfilePath.lexically_normal();
162 cert = ndn::io::load<security::Certificate>(certfilePath);
163 if (cert ==
nullptr) {
164 NDN_THROW(ConfigFile::Error(
"cannot load certfile '" + certfilePath.native() +
165 "' for authorize[" + std::to_string(authSectionIndex) +
"]"));
171 privSection = &authSection.get_child(
"privileges");
173 catch (
const boost::property_tree::ptree_error&) {
174 NDN_THROW(ConfigFile::Error(
"'privileges' is missing under authorize[" +
175 std::to_string(authSectionIndex) +
"]"));
178 if (privSection->empty()) {
179 NFD_LOG_WARN(
"No privileges granted to certificate " << certfile);
181 for (
const auto& kv : *privSection) {
182 const std::string& module = kv.first;
183 auto found = m_validators.find(module);
184 if (found == m_validators.end()) {
185 NDN_THROW(ConfigFile::Error(
"unknown module '" + module +
186 "' under authorize[" + std::to_string(authSectionIndex) +
"]"));
194 found->second = make_shared<security::Validator>(make_unique<security::ValidationPolicyAcceptAll>(),
195 make_unique<security::CertificateFetcherOffline>());
196 NFD_LOG_INFO(
"authorize module=" << module <<
" signer=any");
199 const Name& keyName = cert->getKeyName();
200 security::Certificate certCopy = *cert;
201 found->second->loadAnchor(certfile, std::move(certCopy));
202 NFD_LOG_INFO(
"authorize module=" << module <<
" signer=" << keyName <<
" certfile=" << certfile);
210 ndn::mgmt::Authorization
213 m_validators[module];
215 return [module,
self = shared_from_this()] (
const Name&,
const Interest& interest,
216 const ndn::mgmt::ControlParameters*,
217 const ndn::mgmt::AcceptContinuation& accept,
218 const ndn::mgmt::RejectContinuation& reject) {
219 auto validator =
self->m_validators.at(module);
221 auto successCb = [accept, validator] (
const Interest& interest1) {
223 BOOST_ASSERT(signer1 ||
224 dynamic_cast<security::ValidationPolicyAcceptAll*
>(&validator->getPolicy()) !=
nullptr);
225 std::string signer = signer1.value_or(
"*");
226 NFD_LOG_DEBUG(
"accept " << interest1.getName() <<
" signer=" << signer);
230 using ndn::security::ValidationError;
231 auto failureCb = [reject] (
const Interest& interest1,
const ValidationError& err) {
232 auto reply = ndn::mgmt::RejectReply::STATUS403;
233 if (err.getCode() == ValidationError::MALFORMED_SIGNATURE ||
234 err.getCode() == ValidationError::INVALID_KEY_LOCATOR) {
236 reply = ndn::mgmt::RejectReply::SILENT;
238 NFD_LOG_DEBUG(
"reject " << interest1.getName() <<
" signer=" <<
244 validator->validate(interest, successCb, failureCb);
247 NFD_LOG_DEBUG(
"reject " << interest.getName() <<
" signer=" <<
249 reject(ndn::mgmt::RejectReply::STATUS403);
Provides ControlCommand authorization according to NFD's configuration file.
ndn::mgmt::Authorization makeAuthorization(const std::string &module, const std::string &verb)
Returns an Authorization function for module/verb command.
void setConfigFile(ConfigFile &configFile)
static shared_ptr< CommandAuthenticator > create()
Configuration file parsing utility.
void addSectionHandler(const std::string §ionName, ConfigSectionHandler subscriber)
Setup notification of configuration file sections.
#define NFD_LOG_INIT(name)
ndn::SimpleTag< Name, 20 > SignerTag
An Interest tag to store the command signer.
boost::property_tree::ptree ConfigSection
A configuration file section.
static std::optional< std::string > getSignerFromTag(const Interest &interest)
Obtain signer from a SignerTag attached to interest, if available.