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/security/identity-certificate.hpp>
30 #include <ndn-cxx/security/validator-null.hpp>
31 #include <ndn-cxx/util/io.hpp>
32 
33 #include <boost/filesystem.hpp>
34 
35 namespace nfd {
36 
37 NFD_LOG_INIT("CommandAuthenticator");
38 // INFO: configuration change, etc
39 // DEBUG: per authentication request result
40 
41 shared_ptr<CommandAuthenticator>
43 {
44  return shared_ptr<CommandAuthenticator>(new CommandAuthenticator());
45 }
46 
47 CommandAuthenticator::CommandAuthenticator()
48  : m_validator(make_unique<ndn::ValidatorNull>())
49 {
50 }
51 
52 void
54 {
55  configFile.addSectionHandler("authorizations",
56  bind(&CommandAuthenticator::processConfig, this, _1, _2, _3));
57 }
58 
59 void
60 CommandAuthenticator::processConfig(const ConfigSection& section, bool isDryRun, const std::string& filename)
61 {
62  if (!isDryRun) {
63  NFD_LOG_INFO("clear-authorizations");
64  for (auto& kv : m_moduleAuth) {
65  kv.second.allowAny = false;
66  kv.second.certs.clear();
67  }
68  }
69 
70  if (section.empty()) {
71  BOOST_THROW_EXCEPTION(ConfigFile::Error("'authorize' is missing under 'authorizations'"));
72  }
73 
74  int authSectionIndex = 0;
75  for (const auto& kv : section) {
76  if (kv.first != "authorize") {
77  BOOST_THROW_EXCEPTION(ConfigFile::Error(
78  "'" + kv.first + "' section is not permitted under 'authorizations'"));
79  }
80  const ConfigSection& authSection = kv.second;
81 
82  std::string certfile;
83  try {
84  certfile = authSection.get<std::string>("certfile");
85  }
86  catch (const boost::property_tree::ptree_error&) {
87  BOOST_THROW_EXCEPTION(ConfigFile::Error(
88  "'certfile' is missing under authorize[" + to_string(authSectionIndex) + "]"));
89  }
90 
91  bool isAny = false;
92  shared_ptr<ndn::IdentityCertificate> cert;
93  if (certfile == "any") {
94  isAny = true;
95  NFD_LOG_WARN("'certfile any' is intended for demo purposes only and "
96  "SHOULD NOT be used in production environments");
97  }
98  else {
99  using namespace boost::filesystem;
100  path certfilePath = absolute(certfile, path(filename).parent_path());
101  cert = ndn::io::load<ndn::IdentityCertificate>(certfilePath.string());
102  if (cert == nullptr) {
103  BOOST_THROW_EXCEPTION(ConfigFile::Error(
104  "cannot load certfile " + certfilePath.string() +
105  " for authorize[" + to_string(authSectionIndex) + "]"));
106  }
107  }
108 
109  const ConfigSection* privSection = nullptr;
110  try {
111  privSection = &authSection.get_child("privileges");
112  }
113  catch (const boost::property_tree::ptree_error&) {
114  BOOST_THROW_EXCEPTION(ConfigFile::Error(
115  "'privileges' is missing under authorize[" + to_string(authSectionIndex) + "]"));
116  }
117 
118  if (privSection->empty()) {
119  NFD_LOG_WARN("No privileges granted to certificate " << certfile);
120  }
121  for (const auto& kv : *privSection) {
122  const std::string& module = kv.first;
123  auto found = m_moduleAuth.find(module);
124  if (found == m_moduleAuth.end()) {
125  BOOST_THROW_EXCEPTION(ConfigFile::Error(
126  "unknown module '" + module + "' under authorize[" + to_string(authSectionIndex) + "]"));
127  }
128 
129  if (isDryRun) {
130  continue;
131  }
132 
133  if (isAny) {
134  found->second.allowAny = true;
135  NFD_LOG_INFO("authorize module=" << module << " signer=any");
136  }
137  else {
138  const Name& keyName = cert->getPublicKeyName();
139  found->second.certs.emplace(keyName, cert->getPublicKeyInfo());
140  NFD_LOG_INFO("authorize module=" << module << " signer=" << keyName <<
141  " certfile=" << certfile);
142  }
143  }
144 
145  ++authSectionIndex;
146  }
147 }
148 
150 CommandAuthenticator::makeAuthorization(const std::string& module, const std::string& verb)
151 {
152  m_moduleAuth[module]; // declares module, so that privilege is recognized
153 
154  auto self = this->shared_from_this();
155  return [=] (const Name& prefix, const Interest& interest,
156  const ndn::mgmt::ControlParameters* params,
157  const ndn::mgmt::AcceptContinuation& accept,
158  const ndn::mgmt::RejectContinuation& reject) {
159  const AuthorizedCerts& authorized = self->m_moduleAuth.at(module);
160  if (authorized.allowAny) {
161  NFD_LOG_DEBUG("accept " << interest.getName() << " allowAny");
162  accept("*");
163  return;
164  }
165 
166  bool isOk = false;
167  Name keyName;
168  std::tie(isOk, keyName) = CommandAuthenticator::extractKeyName(interest);
169  if (!isOk) {
170  NFD_LOG_DEBUG("reject " << interest.getName() << " bad-KeyLocator");
172  return;
173  }
174 
175  auto found = authorized.certs.find(keyName);
176  if (found == authorized.certs.end()) {
177  NFD_LOG_DEBUG("reject " << interest.getName() << " signer=" << keyName << " not-authorized");
179  return;
180  }
181 
182  bool hasGoodSig = ndn::Validator::verifySignature(interest, found->second);
183  if (!hasGoodSig) {
184  NFD_LOG_DEBUG("reject " << interest.getName() << " signer=" << keyName << " bad-sig");
186  return;
187  }
188 
189  self->m_validator.validate(interest,
190  bind([=] {
191  NFD_LOG_DEBUG("accept " << interest.getName() << " signer=" << keyName);
192  accept(keyName.toUri());
193  }),
194  bind([=] {
195  NFD_LOG_DEBUG("reject " << interest.getName() << " signer=" << keyName << " invalid-timestamp");
197  }));
198  };
199 }
200 
201 std::pair<bool, Name>
202 CommandAuthenticator::extractKeyName(const Interest& interest)
203 {
204  const Name& name = interest.getName();
205  if (name.size() < ndn::signed_interest::MIN_LENGTH) {
206  return {false, Name()};
207  }
208 
209  ndn::SignatureInfo sig;
210  try {
211  sig.wireDecode(name[ndn::signed_interest::POS_SIG_INFO].blockFromValue());
212  }
213  catch (const tlv::Error&) {
214  return {false, Name()};
215  }
216 
217  if (!sig.hasKeyLocator()) {
218  return {false, Name()};
219  }
220 
221  const ndn::KeyLocator& keyLocator = sig.getKeyLocator();
222  if (keyLocator.getType() != ndn::KeyLocator::KeyLocator_Name) {
223  return {false, Name()};
224  }
225 
226  try {
228  }
229  catch (const ndn::IdentityCertificate::Error&) {
230  return {false, Name()};
231  }
232 }
233 
234 } // namespace nfd
static Name certificateNameToPublicKeyName(const Name &certificateName)
Get the public key name from the full certificate name.
const KeyLocator & getKeyLocator() const
Get KeyLocator.
std::string toUri() const
Encode this name as a URI.
Definition: name.cpp:171
reply with a ControlResponse where StatusCode is 403
configuration file parsing utility
Definition: config-file.hpp:50
const Name & getName() const
get Name element
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
indicates KeyLocator contains a Name
Definition: key-locator.hpp:49
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:56
void setConfigFile(ConfigFile &configFile)
const size_t MIN_LENGTH
minimal number of components for Command Interest
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:79
bool hasKeyLocator() const
Check if KeyLocator is set.
ndn::mgmt::Authorization makeAuthorization(const std::string &module, const std::string &verb)
boost::property_tree::ptree ConfigSection
Name abstraction to represent an absolute name.
Definition: name.hpp:46
base class for a struct that contains ControlCommand parameters
size_t size() const
Get the number of components.
Definition: name.hpp:400
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
void wireDecode(const Block &wire)
Decode from a wire format.
provides ControlCommand authorization according to NFD configuration file
static shared_ptr< CommandAuthenticator > create()
const ssize_t POS_SIG_INFO
Type getType() const
std::string to_string(const V &v)
Definition: backports.hpp:51
static bool verifySignature(const Data &data, const v1::PublicKey &publicKey)
Verify the data using the publicKey.
Definition: validator.cpp:105
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
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
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
const Name & getName() const
Definition: interest.hpp:215