blob: ea596b10fc761d54a64089c36fddcd3fd3338608 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014 Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
**/
#include "command-validator.hpp"
#include "core/logger.hpp"
#include <ndn-cxx/util/io.hpp>
#include <ndn-cxx/security/identity-certificate.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
namespace nfd {
NFD_LOG_INIT("CommandValidator");
CommandValidator::CommandValidator()
{
}
CommandValidator::~CommandValidator()
{
}
void
CommandValidator::setConfigFile(ConfigFile& configFile)
{
configFile.addSectionHandler("authorizations",
bind(&CommandValidator::onConfig, this, _1, _2, _3));
}
static inline void
aggregateErrors(std::stringstream& ss, const std::string& msg)
{
if (!ss.str().empty())
{
ss << "\n";
}
ss << msg;
}
void
CommandValidator::onConfig(const ConfigSection& section,
bool isDryRun,
const std::string& filename)
{
using namespace boost::filesystem;
const ConfigSection EMPTY_SECTION;
if (section.begin() == section.end())
{
throw ConfigFile::Error("No authorize sections found");
}
std::stringstream dryRunErrors;
ConfigSection::const_iterator authIt;
for (authIt = section.begin(); authIt != section.end(); authIt++)
{
std::string certfile;
try
{
certfile = authIt->second.get<std::string>("certfile");
}
catch (const std::runtime_error& e)
{
std::string msg = "No certfile specified";
if (!isDryRun)
{
throw ConfigFile::Error(msg);
}
aggregateErrors(dryRunErrors, msg);
continue;
}
shared_ptr<ndn::IdentityCertificate> id;
if (certfile != "any")
{
path certfilePath = absolute(certfile, path(filename).parent_path());
NFD_LOG_DEBUG("generated certfile path: " << certfilePath.native());
std::ifstream in;
in.open(certfilePath.c_str());
if (!in.is_open())
{
std::string msg = "Unable to open certificate file " + certfilePath.native();
if (!isDryRun)
{
throw ConfigFile::Error(msg);
}
aggregateErrors(dryRunErrors, msg);
continue;
}
try
{
id = ndn::io::load<ndn::IdentityCertificate>(in);
}
catch (const std::runtime_error& error)
{
// do nothing
}
if (!static_cast<bool>(id)) {
std::string msg = "Malformed certificate file " + certfilePath.native();
if (!isDryRun)
{
throw ConfigFile::Error(msg);
}
aggregateErrors(dryRunErrors, msg);
continue;
}
in.close();
}
std::string keyNameForLogging;
if (static_cast<bool>(id))
keyNameForLogging = id->getPublicKeyName().toUri();
else
{
keyNameForLogging = "wildcard";
NFD_LOG_WARN("Wildcard identity is intended for demo purpose only and " <<
"SHOULD NOT be used in production environment");
}
const ConfigSection* privileges = 0;
try
{
privileges = &authIt->second.get_child("privileges");
}
catch (const std::runtime_error& error)
{
std::string msg = "No privileges section found for certificate file " +
certfile + " (" + keyNameForLogging + ")";
if (!isDryRun)
{
throw ConfigFile::Error(msg);
}
aggregateErrors(dryRunErrors, msg);
continue;
}
if (privileges->begin() == privileges->end())
{
NFD_LOG_WARN("No privileges specified for certificate file " << certfile
<< " (" << keyNameForLogging << ")");
}
ConfigSection::const_iterator privIt;
for (privIt = privileges->begin(); privIt != privileges->end(); privIt++)
{
const std::string& privilegeName = privIt->first;
if (m_supportedPrivileges.find(privilegeName) != m_supportedPrivileges.end())
{
NFD_LOG_INFO("Giving privilege \"" << privilegeName
<< "\" to identity " << keyNameForLogging);
if (!isDryRun)
{
const std::string regex = "^<localhost><nfd><" + privilegeName + ">";
if (static_cast<bool>(id))
m_validator.addInterestRule(regex, *id);
else
m_validator.addInterestBypassRule(regex);
}
}
else
{
// Invalid configuration
std::string msg = "Invalid privilege \"" + privilegeName +
"\" for certificate file " + certfile + " (" + keyNameForLogging + ")";
if (!isDryRun)
{
throw ConfigFile::Error(msg);
}
aggregateErrors(dryRunErrors, msg);
}
}
}
if (!dryRunErrors.str().empty())
{
throw ConfigFile::Error(dryRunErrors.str());
}
}
void
CommandValidator::addSupportedPrivilege(const std::string& privilege)
{
if (m_supportedPrivileges.find(privilege) != m_supportedPrivileges.end())
{
throw CommandValidator::Error("Duplicated privilege: " + privilege);
}
m_supportedPrivileges.insert(privilege);
}
} // namespace nfd