NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
command-authenticator.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
27 #include "core/logger.hpp"
28 
29 #include <ndn-cxx/tag.hpp>
30 #include <ndn-cxx/security/v2/certificate-fetcher-offline.hpp>
31 #include <ndn-cxx/security/v2/certificate-request.hpp>
32 #include <ndn-cxx/security/v2/validation-policy.hpp>
33 #include <ndn-cxx/security/v2/validation-policy-accept-all.hpp>
34 #include <ndn-cxx/security/v2/validation-policy-command-interest.hpp>
35 #include <ndn-cxx/security/v2/validator.hpp>
36 #include <ndn-cxx/util/io.hpp>
37 
38 #include <boost/filesystem.hpp>
39 
40 namespace sec2 = ndn::security::v2;
41 
42 namespace nfd {
43 
44 NFD_LOG_INIT("CommandAuthenticator");
45 // INFO: configuration change, etc
46 // DEBUG: per authentication request result
47 
51 
55 getSignerFromTag(const Interest& interest)
56 {
57  shared_ptr<SignerTag> signerTag = interest.getTag<SignerTag>();
58  if (signerTag == nullptr) {
59  return ndn::nullopt;
60  }
61  else {
62  return signerTag->get().toUri();
63  }
64 }
65 
69 {
70 public:
71  void
72  checkPolicy(const Interest& interest, const shared_ptr<sec2::ValidationState>& state,
73  const ValidationContinuation& continueValidation) final
74  {
75  Name klName = getKeyLocatorName(interest, *state);
76  if (!state->getOutcome()) { // already failed
77  return;
78  }
79 
80  // SignerTag must be placed on the 'original Interest' in ValidationState to be available for
81  // InterestValidationSuccessCallback. The 'interest' parameter refers to a different instance
82  // which is copied into 'original Interest'.
83  auto state1 = dynamic_pointer_cast<sec2::InterestValidationState>(state);
84  state1->getOriginalInterest().setTag(make_shared<SignerTag>(klName));
85 
86  continueValidation(make_shared<sec2::CertificateRequest>(Interest(klName)), state);
87  }
88 
89  void
90  checkPolicy(const Data& data, const shared_ptr<sec2::ValidationState>& state,
91  const ValidationContinuation& continueValidation) final
92  {
93  // Non-certificate Data are not handled by CommandAuthenticator.
94  // Non-anchor certificates cannot be retrieved by offline fetcher.
95  BOOST_ASSERT_MSG(false, "Data should not be passed to this policy");
96  }
97 };
98 
99 shared_ptr<CommandAuthenticator>
101 {
102  return shared_ptr<CommandAuthenticator>(new CommandAuthenticator);
103 }
104 
105 CommandAuthenticator::CommandAuthenticator() = default;
106 
107 void
109 {
110  configFile.addSectionHandler("authorizations",
111  bind(&CommandAuthenticator::processConfig, this, _1, _2, _3));
112 }
113 
114 void
115 CommandAuthenticator::processConfig(const ConfigSection& section, bool isDryRun, const std::string& filename)
116 {
117  if (!isDryRun) {
118  NFD_LOG_INFO("clear-authorizations");
119  for (auto& kv : m_validators) {
120  kv.second = make_shared<sec2::Validator>(
121  make_unique<sec2::ValidationPolicyCommandInterest>(make_unique<CommandAuthenticatorValidationPolicy>()),
122  make_unique<sec2::CertificateFetcherOffline>());
123  }
124  }
125 
126  if (section.empty()) {
127  BOOST_THROW_EXCEPTION(ConfigFile::Error("'authorize' is missing under 'authorizations'"));
128  }
129 
130  int authSectionIndex = 0;
131  for (const auto& kv : section) {
132  if (kv.first != "authorize") {
133  BOOST_THROW_EXCEPTION(ConfigFile::Error(
134  "'" + kv.first + "' section is not permitted under 'authorizations'"));
135  }
136  const ConfigSection& authSection = kv.second;
137 
138  std::string certfile;
139  try {
140  certfile = authSection.get<std::string>("certfile");
141  }
142  catch (const boost::property_tree::ptree_error&) {
143  BOOST_THROW_EXCEPTION(ConfigFile::Error(
144  "'certfile' is missing under authorize[" + to_string(authSectionIndex) + "]"));
145  }
146 
147  bool isAny = false;
148  shared_ptr<sec2::Certificate> cert;
149  if (certfile == "any") {
150  isAny = true;
151  NFD_LOG_WARN("'certfile any' is intended for demo purposes only and "
152  "SHOULD NOT be used in production environments");
153  }
154  else {
155  using namespace boost::filesystem;
156  path certfilePath = absolute(certfile, path(filename).parent_path());
157  cert = ndn::io::load<sec2::Certificate>(certfilePath.string());
158  if (cert == nullptr) {
159  BOOST_THROW_EXCEPTION(ConfigFile::Error(
160  "cannot load certfile " + certfilePath.string() +
161  " for authorize[" + to_string(authSectionIndex) + "]"));
162  }
163  }
164 
165  const ConfigSection* privSection = nullptr;
166  try {
167  privSection = &authSection.get_child("privileges");
168  }
169  catch (const boost::property_tree::ptree_error&) {
170  BOOST_THROW_EXCEPTION(ConfigFile::Error(
171  "'privileges' is missing under authorize[" + to_string(authSectionIndex) + "]"));
172  }
173 
174  if (privSection->empty()) {
175  NFD_LOG_WARN("No privileges granted to certificate " << certfile);
176  }
177  for (const auto& kv : *privSection) {
178  const std::string& module = kv.first;
179  auto found = m_validators.find(module);
180  if (found == m_validators.end()) {
181  BOOST_THROW_EXCEPTION(ConfigFile::Error(
182  "unknown module '" + module + "' under authorize[" + to_string(authSectionIndex) + "]"));
183  }
184 
185  if (isDryRun) {
186  continue;
187  }
188 
189  if (isAny) {
190  found->second = make_shared<sec2::Validator>(make_unique<sec2::ValidationPolicyAcceptAll>(),
191  make_unique<sec2::CertificateFetcherOffline>());
192  NFD_LOG_INFO("authorize module=" << module << " signer=any");
193  }
194  else {
195  const Name& keyName = cert->getKeyName();
196  sec2::Certificate certCopy = *cert;
197  found->second->loadAnchor(certfile, std::move(certCopy));
198  NFD_LOG_INFO("authorize module=" << module << " signer=" << keyName <<
199  " certfile=" << certfile);
200  }
201  }
202 
203  ++authSectionIndex;
204  }
205 }
206 
208 CommandAuthenticator::makeAuthorization(const std::string& module, const std::string& verb)
209 {
210  m_validators[module]; // declares module, so that privilege is recognized
211 
212  auto self = this->shared_from_this();
213  return [=] (const Name& prefix, const Interest& interest,
214  const ndn::mgmt::ControlParameters* params,
216  const ndn::mgmt::RejectContinuation& reject) {
217  shared_ptr<sec2::Validator> validator = self->m_validators.at(module);
218  validator->validate(interest,
219  [accept, validator] (const Interest& interest1) {
220  auto signer1 = getSignerFromTag(interest1);
221  BOOST_ASSERT(signer1 || // signer must be available unless 'certfile any'
222  dynamic_cast<sec2::ValidationPolicyAcceptAll*>(&validator->getPolicy()) != nullptr);
223  std::string signer = signer1.value_or("*");
224  NFD_LOG_DEBUG("accept " << interest1.getName() << " signer=" << signer);
225  accept(signer);
226  },
227  [reject] (const Interest& interest1, const sec2::ValidationError& err) {
228  NFD_LOG_DEBUG("reject " << interest1.getName() << " signer=" <<
229  getSignerFromTag(interest1).value_or("?") << ' ' << err);
230 
232  RejectReply reply = RejectReply::STATUS403;
233  using ErrCode = sec2::ValidationError::Code;
234  switch (err.getCode()) {
235  case ErrCode::NO_SIGNATURE:
236  case ErrCode::INVALID_KEY_LOCATOR:
237  reply = RejectReply::SILENT;
238  break;
239  case ErrCode::POLICY_ERROR:
240  if (interest1.getName().size() < ndn::command_interest::MIN_SIZE) { // "name too short"
241  reply = RejectReply::SILENT;
242  }
243  break;
244  default:
245  break;
246  }
247  reject(reply);
248  });
249  };
250 }
251 
252 } // namespace nfd
constexpr nullopt_t nullopt
const Name & getName() const
Definition: interest.hpp:139
The certificate following the certificate format naming convention.
Definition: certificate.hpp:81
Accept any value the remote endpoint offers.
Definition: enabled.hpp:194
RejectReply
indicate how to reply in case authorization is rejected
Definition: dispatcher.hpp:49
configuration file parsing utility
Definition: config-file.hpp:58
a validation policy that only permits Interest signed by a trust anchor
void checkPolicy(const Interest &interest, const shared_ptr< sec2::ValidationState > &state, const ValidationContinuation &continueValidation) final
Check interest against the policy.
Code
Known validation error code.
represents an Interest packet
Definition: interest.hpp:42
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
std::function< void(RejectReply act)> RejectContinuation
a function to be called if authorization is rejected
Definition: dispatcher.hpp:60
std::function< void(const std::string &requester)> AcceptContinuation
a function to be called if authorization is successful
Definition: dispatcher.hpp:45
Abstraction that implements validation policy for Data and Interest packets.
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:56
void setTag(shared_ptr< T > tag) const
set a tag item
Definition: tag-host.hpp:80
void setConfigFile(ConfigFile &configFile)
provides a tag type for simple types
Definition: tag.hpp:58
std::function< void(const shared_ptr< CertificateRequest > &certRequest, const shared_ptr< ValidationState > &state)> ValidationContinuation
static Name getKeyLocatorName(const SignatureInfo &si, ValidationState &state)
Validation state for an interest packet.
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
void addSectionHandler(const std::string &sectionName, ConfigSectionHandler subscriber)
setup notification of configuration file sections
Definition: config-file.cpp:76
ndn::mgmt::Authorization makeAuthorization(const std::string &module, const std::string &verb)
size_t size() const
Get number of components.
Definition: name.hpp:154
const size_t MIN_SIZE
minimal number of components for Command Interest
boost::property_tree::ptree ConfigSection
a config file section
Represents an absolute name.
Definition: name.hpp:42
base class for a struct that contains ControlCommand parameters
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
static shared_ptr< CommandAuthenticator > create()
Validation error code and optional detailed error message.
shared_ptr< T > getTag() const
get a tag item
Definition: tag-host.hpp:67
std::string to_string(const V &v)
Definition: backports.hpp:84
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
Represents a Data packet.
Definition: data.hpp:35
std::function< void(const Name &prefix, const Interest &interest, const ControlParameters *params, const AcceptContinuation &accept, const RejectContinuation &reject)> Authorization
a function that performs authorization
Definition: dispatcher.hpp:77
static ndn::optional< std::string > getSignerFromTag(const Interest &interest)
obtain signer from SignerTag attached to Interest, if available
void checkPolicy(const Data &data, const shared_ptr< sec2::ValidationState > &state, const ValidationContinuation &continueValidation) final
Check data against the policy.