NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: 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; -*- */
2 /*
3  * Copyright (c) 2014-2019, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
27 #include "common/logger.hpp"
28 
29 #include <ndn-cxx/tag.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 
45 // INFO: configuration change, etc
46 // DEBUG: per authentication request result
47 
51 
54 static optional<std::string>
55 getSignerFromTag(const Interest& interest)
56 {
57  shared_ptr<SignerTag> signerTag = interest.getTag<SignerTag>();
58  if (signerTag == nullptr) {
59  return 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  NDN_THROW(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  NDN_THROW(ConfigFile::Error("'" + kv.first + "' section is not permitted under 'authorizations'"));
134  }
135  const ConfigSection& authSection = kv.second;
136 
137  std::string certfile;
138  try {
139  certfile = authSection.get<std::string>("certfile");
140  }
141  catch (const boost::property_tree::ptree_error&) {
142  NDN_THROW(ConfigFile::Error("'certfile' is missing under authorize[" +
143  to_string(authSectionIndex) + "]"));
144  }
145 
146  bool isAny = false;
147  shared_ptr<sec2::Certificate> cert;
148  if (certfile == "any") {
149  isAny = true;
150  NFD_LOG_WARN("'certfile any' is intended for demo purposes only and "
151  "SHOULD NOT be used in production environments");
152  }
153  else {
154  using namespace boost::filesystem;
155  path certfilePath = absolute(certfile, path(filename).parent_path());
156  cert = ndn::io::load<sec2::Certificate>(certfilePath.string());
157  if (cert == nullptr) {
158  NDN_THROW(ConfigFile::Error("cannot load certfile " + certfilePath.string() +
159  " for authorize[" + to_string(authSectionIndex) + "]"));
160  }
161  }
162 
163  const ConfigSection* privSection = nullptr;
164  try {
165  privSection = &authSection.get_child("privileges");
166  }
167  catch (const boost::property_tree::ptree_error&) {
168  NDN_THROW(ConfigFile::Error("'privileges' is missing under authorize[" +
169  to_string(authSectionIndex) + "]"));
170  }
171 
172  if (privSection->empty()) {
173  NFD_LOG_WARN("No privileges granted to certificate " << certfile);
174  }
175  for (const auto& kv : *privSection) {
176  const std::string& module = kv.first;
177  auto found = m_validators.find(module);
178  if (found == m_validators.end()) {
179  NDN_THROW(ConfigFile::Error("unknown module '" + module +
180  "' under authorize[" + to_string(authSectionIndex) + "]"));
181  }
182 
183  if (isDryRun) {
184  continue;
185  }
186 
187  if (isAny) {
188  found->second = make_shared<sec2::Validator>(make_unique<sec2::ValidationPolicyAcceptAll>(),
189  make_unique<sec2::CertificateFetcherOffline>());
190  NFD_LOG_INFO("authorize module=" << module << " signer=any");
191  }
192  else {
193  const Name& keyName = cert->getKeyName();
194  sec2::Certificate certCopy = *cert;
195  found->second->loadAnchor(certfile, std::move(certCopy));
196  NFD_LOG_INFO("authorize module=" << module << " signer=" << keyName << " certfile=" << certfile);
197  }
198  }
199 
200  ++authSectionIndex;
201  }
202 }
203 
205 CommandAuthenticator::makeAuthorization(const std::string& module, const std::string& verb)
206 {
207  m_validators[module]; // declares module, so that privilege is recognized
208 
209  auto self = this->shared_from_this();
210  return [=] (const Name&, const Interest& interest,
212  const ndn::mgmt::AcceptContinuation& accept,
213  const ndn::mgmt::RejectContinuation& reject) {
214  auto validator = self->m_validators.at(module);
215  auto successCb = [accept, validator] (const Interest& interest1) {
216  auto signer1 = getSignerFromTag(interest1);
217  BOOST_ASSERT(signer1 || // signer must be available unless 'certfile any'
218  dynamic_cast<sec2::ValidationPolicyAcceptAll*>(&validator->getPolicy()) != nullptr);
219  std::string signer = signer1.value_or("*");
220  NFD_LOG_DEBUG("accept " << interest1.getName() << " signer=" << signer);
221  accept(signer);
222  };
223  auto failureCb = [reject] (const Interest& interest1, const sec2::ValidationError& err) {
225  RejectReply reply = RejectReply::STATUS403;
226  switch (err.getCode()) {
229  reply = RejectReply::SILENT;
230  break;
232  if (interest1.getName().size() < ndn::command_interest::MIN_SIZE) { // "name too short"
233  reply = RejectReply::SILENT;
234  }
235  break;
236  }
237  NFD_LOG_DEBUG("reject " << interest1.getName() << " signer=" <<
238  getSignerFromTag(interest1).value_or("?") << " reason=" << err);
239  reject(reply);
240  };
241 
242  if (validator) {
243  validator->validate(interest, successCb, failureCb);
244  }
245  else {
246  NFD_LOG_DEBUG("reject " << interest.getName() << " signer=" <<
247  getSignerFromTag(interest).value_or("?") << " reason=Unauthorized");
249  }
250  };
251 }
252 
253 } // namespace nfd
ndn::security::v2::ValidationError
Validation error code and optional detailed error message.
Definition: validation-error.hpp:35
NFD_LOG_INFO
#define NFD_LOG_INFO
Definition: logger.hpp:39
ndn::mgmt::AcceptContinuation
std::function< void(const std::string &requester)> AcceptContinuation
a function to be called if authorization is successful
Definition: dispatcher.hpp:45
nonstd::optional_lite::std11::move
T & move(T &t)
Definition: optional.hpp:421
nfd::CommandAuthenticator::makeAuthorization
ndn::mgmt::Authorization makeAuthorization(const std::string &module, const std::string &verb)
Definition: command-authenticator.cpp:205
ndn::tlv::Interest
@ Interest
Definition: tlv.hpp:65
nfd::CommandAuthenticator::setConfigFile
void setConfigFile(ConfigFile &configFile)
Definition: command-authenticator.cpp:108
certificate-request.hpp
validator.hpp
nfd::CommandAuthenticator::create
static shared_ptr< CommandAuthenticator > create()
Definition: command-authenticator.cpp:100
ndn::SimpleTag
provides a tag type for simple types
Definition: tag.hpp:59
ndn::Name::size
size_t size() const
Returns the number of components.
Definition: name.hpp:153
ndn::mgmt::RejectReply
RejectReply
indicate how to reply in case authorization is rejected
Definition: dispatcher.hpp:49
validation-policy-command-interest.hpp
nfd::getSignerFromTag
static optional< std::string > getSignerFromTag(const Interest &interest)
obtain signer from SignerTag attached to Interest, if available
Definition: command-authenticator.cpp:55
ndn::security::v2::ValidationError::POLICY_ERROR
@ POLICY_ERROR
Definition: validation-error.hpp:51
ndn::TagHost::getTag
shared_ptr< T > getTag() const
get a tag item
Definition: tag-host.hpp:66
tag.hpp
ndn::security::v2::ValidationPolicy::ValidationContinuation
std::function< void(const shared_ptr< CertificateRequest > &certRequest, const shared_ptr< ValidationState > &state)> ValidationContinuation
Definition: validation-policy.hpp:41
nfd::ConfigFile::addSectionHandler
void addSectionHandler(const std::string &sectionName, ConfigSectionHandler subscriber)
setup notification of configuration file sections
Definition: config-file.cpp:77
validation-policy.hpp
ndn::mgmt::ControlParameters
base class for a struct that contains ControlCommand parameters
Definition: control-parameters.hpp:33
ndn::security::v2::ValidationPolicy
Abstraction that implements validation policy for Data and Interest packets.
Definition: validation-policy.hpp:38
NFD_LOG_WARN
#define NFD_LOG_WARN
Definition: logger.hpp:40
ndn::Name
Represents an absolute name.
Definition: name.hpp:44
io.hpp
command-authenticator.hpp
ns3::ndn::Name
Name
Definition: ndn-common.cpp:25
nfd
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
ndn::security::v2::Certificate
The certificate following the certificate format naming convention.
Definition: certificate.hpp:82
ndn::security::v2::ValidationError::INVALID_KEY_LOCATOR
@ INVALID_KEY_LOCATOR
Definition: validation-error.hpp:50
nfd::ConfigFile
configuration file parsing utility
Definition: config-file.hpp:58
certificate-fetcher-offline.hpp
NDN_THROW
#define NDN_THROW(e)
Definition: exception.hpp:61
ndn::mgmt::Authorization
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
nonstd::optional_lite::nullopt
const nullopt_t nullopt((nullopt_t::init()))
ndn::command_interest::MIN_SIZE
const size_t MIN_SIZE
minimal number of components for Command Interest
Definition: security-common.hpp:51
validation-policy-accept-all.hpp
ndn::Interest
Represents an Interest packet.
Definition: interest.hpp:44
ndn::Data
Represents a Data packet.
Definition: data.hpp:36
NFD_LOG_DEBUG
#define NFD_LOG_DEBUG
Definition: logger.hpp:38
nfd::ConfigSection
boost::property_tree::ptree ConfigSection
a config file section
Definition: ndn-l3-protocol.hpp:39
ndn::mgmt::RejectReply::STATUS403
@ STATUS403
reply with a ControlResponse where StatusCode is 403
ndn::SimpleTag::get
constexpr const T & get() const noexcept
Definition: tag.hpp:86
ndn::to_string
std::string to_string(const T &val)
Definition: backports.hpp:102
nfd::CommandAuthenticatorValidationPolicy::checkPolicy
void checkPolicy(const Data &data, const shared_ptr< sec2::ValidationState > &state, const ValidationContinuation &continueValidation) final
Check data against the policy.
Definition: command-authenticator.cpp:90
ndn::security::v2::ValidationError::NO_SIGNATURE
@ NO_SIGNATURE
Definition: validation-error.hpp:44
ndn::Interest::getName
const Name & getName() const noexcept
Definition: interest.hpp:121
ndn::security::v2
Definition: command-authenticator.hpp:35
nfd::CommandAuthenticatorValidationPolicy::checkPolicy
void checkPolicy(const Interest &interest, const shared_ptr< sec2::ValidationState > &state, const ValidationContinuation &continueValidation) final
Check interest against the policy.
Definition: command-authenticator.cpp:72
ndn::mgmt::RejectContinuation
std::function< void(RejectReply reply)> RejectContinuation
a function to be called if authorization is rejected
Definition: dispatcher.hpp:60
nfd::CommandAuthenticatorValidationPolicy
a validation policy that only permits Interest signed by a trust anchor
Definition: command-authenticator.cpp:69
nfd::CommandAuthenticator
Provides ControlCommand authorization according to NFD configuration file.
Definition: command-authenticator.hpp:46
ndn::security::v2::getKeyLocatorName
static Name getKeyLocatorName(const SignatureInfo &si, ValidationState &state)
Definition: validation-policy.cpp:64
ndn::security::v2::ValidationPolicyAcceptAll
A validator policy that accepts any signature of data and interest packets.
Definition: validation-policy-accept-all.hpp:35
NFD_LOG_INIT
#define NFD_LOG_INIT(name)
Definition: logger.hpp:31
logger.hpp