blob: 715b5d58ea44f71a427b48a54d8acd31e16445a4 [file] [log] [blame]
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 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 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070024
25#include "command-validator.hpp"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060026#include "core/logger.hpp"
27
Alexander Afanasyev4a771362014-04-24 21:29:33 -070028#include <ndn-cxx/util/io.hpp>
29#include <ndn-cxx/security/identity-certificate.hpp>
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070030
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060031#include <boost/filesystem.hpp>
Davide Pesavento52a18f92014-04-10 00:55:01 +020032#include <fstream>
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060033
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070034namespace nfd {
35
36NFD_LOG_INIT("CommandValidator");
37
38CommandValidator::CommandValidator()
39{
40
41}
42
43CommandValidator::~CommandValidator()
44{
45
46}
47
48void
49CommandValidator::setConfigFile(ConfigFile& configFile)
50{
51 configFile.addSectionHandler("authorizations",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060052 bind(&CommandValidator::onConfig, this, _1, _2, _3));
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070053}
54
55static inline void
56aggregateErrors(std::stringstream& ss, const std::string& msg)
57{
58 if (!ss.str().empty())
59 {
60 ss << "\n";
61 }
62 ss << msg;
63}
64
65void
66CommandValidator::onConfig(const ConfigSection& section,
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060067 bool isDryRun,
68 const std::string& filename)
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070069{
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060070 using namespace boost::filesystem;
71
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070072 const ConfigSection EMPTY_SECTION;
73
Alexander Afanasyev5959b012014-06-02 19:18:12 +030074 m_validator.reset();
75
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070076 if (section.begin() == section.end())
77 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -070078 BOOST_THROW_EXCEPTION(ConfigFile::Error("No authorize sections found"));
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070079 }
80
81 std::stringstream dryRunErrors;
82 ConfigSection::const_iterator authIt;
83 for (authIt = section.begin(); authIt != section.end(); authIt++)
84 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060085 std::string certfile;
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070086 try
87 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060088 certfile = authIt->second.get<std::string>("certfile");
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070089 }
90 catch (const std::runtime_error& e)
91 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060092 std::string msg = "No certfile specified";
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070093 if (!isDryRun)
94 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -070095 BOOST_THROW_EXCEPTION(ConfigFile::Error(msg));
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070096 }
97 aggregateErrors(dryRunErrors, msg);
98 continue;
99 }
100
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700101 shared_ptr<ndn::IdentityCertificate> id;
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700102
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700103 if (certfile != "any")
104 {
105 path certfilePath = absolute(certfile, path(filename).parent_path());
106 NFD_LOG_DEBUG("generated certfile path: " << certfilePath.native());
107
108 std::ifstream in;
109 in.open(certfilePath.c_str());
110 if (!in.is_open())
111 {
112 std::string msg = "Unable to open certificate file " + certfilePath.native();
113 if (!isDryRun)
114 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700115 BOOST_THROW_EXCEPTION(ConfigFile::Error(msg));
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700116 }
117 aggregateErrors(dryRunErrors, msg);
118 continue;
119 }
120
121 try
122 {
123 id = ndn::io::load<ndn::IdentityCertificate>(in);
124 }
125 catch (const std::runtime_error& error)
126 {
127 // do nothing
128 }
129
130 if (!static_cast<bool>(id)) {
131 std::string msg = "Malformed certificate file " + certfilePath.native();
132 if (!isDryRun)
133 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700134 BOOST_THROW_EXCEPTION(ConfigFile::Error(msg));
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700135 }
136 aggregateErrors(dryRunErrors, msg);
137 continue;
Alexander Afanasyev5d2820d2014-04-24 00:10:31 -0700138 }
Alexander Afanasyev5d2820d2014-04-24 00:10:31 -0700139
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700140 in.close();
141 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700142
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700143 std::string keyNameForLogging;
144 if (static_cast<bool>(id))
145 keyNameForLogging = id->getPublicKeyName().toUri();
146 else
147 {
148 keyNameForLogging = "wildcard";
149 NFD_LOG_WARN("Wildcard identity is intended for demo purpose only and " <<
150 "SHOULD NOT be used in production environment");
151 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700152 const ConfigSection* privileges = 0;
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700153 try
154 {
155 privileges = &authIt->second.get_child("privileges");
156 }
157 catch (const std::runtime_error& error)
158 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600159 std::string msg = "No privileges section found for certificate file " +
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700160 certfile + " (" + keyNameForLogging + ")";
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700161 if (!isDryRun)
162 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700163 BOOST_THROW_EXCEPTION(ConfigFile::Error(msg));
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700164 }
165 aggregateErrors(dryRunErrors, msg);
166 continue;
167 }
168
169 if (privileges->begin() == privileges->end())
170 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600171 NFD_LOG_WARN("No privileges specified for certificate file " << certfile
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700172 << " (" << keyNameForLogging << ")");
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700173 }
174
175 ConfigSection::const_iterator privIt;
176 for (privIt = privileges->begin(); privIt != privileges->end(); privIt++)
177 {
178 const std::string& privilegeName = privIt->first;
179 if (m_supportedPrivileges.find(privilegeName) != m_supportedPrivileges.end())
180 {
181 NFD_LOG_INFO("Giving privilege \"" << privilegeName
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700182 << "\" to identity " << keyNameForLogging);
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700183 if (!isDryRun)
184 {
185 const std::string regex = "^<localhost><nfd><" + privilegeName + ">";
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700186 if (static_cast<bool>(id))
187 m_validator.addInterestRule(regex, *id);
188 else
189 m_validator.addInterestBypassRule(regex);
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700190 }
191 }
192 else
193 {
194 // Invalid configuration
Yingdi Yuc8f214c2014-04-29 20:39:37 -0700195 std::string msg = "Invalid privilege \"" + privilegeName +
196 "\" for certificate file " + certfile + " (" + keyNameForLogging + ")";
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700197 if (!isDryRun)
198 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700199 BOOST_THROW_EXCEPTION(ConfigFile::Error(msg));
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700200 }
201 aggregateErrors(dryRunErrors, msg);
202 }
203 }
204 }
205
206 if (!dryRunErrors.str().empty())
207 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700208 BOOST_THROW_EXCEPTION(ConfigFile::Error(dryRunErrors.str()));
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700209 }
210}
211
212void
213CommandValidator::addSupportedPrivilege(const std::string& privilege)
214{
215 if (m_supportedPrivileges.find(privilege) != m_supportedPrivileges.end())
216 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700217 BOOST_THROW_EXCEPTION(CommandValidator::Error("Duplicated privilege: " + privilege));
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700218 }
219 m_supportedPrivileges.insert(privilege);
220}
221
222} // namespace nfd