blob: 22b825720cdf5ea2553c51241848d4786f233f49 [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
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070028#include <ndn-cpp-dev/util/io.hpp>
29#include <ndn-cpp-dev/security/identity-certificate.hpp>
30
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060031#include <boost/filesystem.hpp>
32
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070033namespace nfd {
34
35NFD_LOG_INIT("CommandValidator");
36
37CommandValidator::CommandValidator()
38{
39
40}
41
42CommandValidator::~CommandValidator()
43{
44
45}
46
47void
48CommandValidator::setConfigFile(ConfigFile& configFile)
49{
50 configFile.addSectionHandler("authorizations",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060051 bind(&CommandValidator::onConfig, this, _1, _2, _3));
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070052}
53
54static inline void
55aggregateErrors(std::stringstream& ss, const std::string& msg)
56{
57 if (!ss.str().empty())
58 {
59 ss << "\n";
60 }
61 ss << msg;
62}
63
64void
65CommandValidator::onConfig(const ConfigSection& section,
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060066 bool isDryRun,
67 const std::string& filename)
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070068{
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060069 using namespace boost::filesystem;
70
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070071 const ConfigSection EMPTY_SECTION;
72
73 if (section.begin() == section.end())
74 {
75 throw ConfigFile::Error("No authorize sections found");
76 }
77
78 std::stringstream dryRunErrors;
79 ConfigSection::const_iterator authIt;
80 for (authIt = section.begin(); authIt != section.end(); authIt++)
81 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060082 std::string certfile;
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070083 try
84 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060085 certfile = authIt->second.get<std::string>("certfile");
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070086 }
87 catch (const std::runtime_error& e)
88 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060089 std::string msg = "No certfile specified";
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070090 if (!isDryRun)
91 {
92 throw ConfigFile::Error(msg);
93 }
94 aggregateErrors(dryRunErrors, msg);
95 continue;
96 }
97
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060098 path certfilePath = absolute(certfile, path(filename).parent_path());
99 NFD_LOG_DEBUG("generated certfile path: " << certfilePath.native());
100
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700101 std::ifstream in;
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600102 in.open(certfilePath.c_str());
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700103 if (!in.is_open())
104 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600105 std::string msg = "Unable to open certificate file " + certfilePath.native();
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700106 if (!isDryRun)
107 {
108 throw ConfigFile::Error(msg);
109 }
110 aggregateErrors(dryRunErrors, msg);
111 continue;
112 }
113
114 shared_ptr<ndn::IdentityCertificate> id;
115 try
116 {
117 id = ndn::io::load<ndn::IdentityCertificate>(in);
118 }
119 catch(const std::runtime_error& error)
120 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600121 std::string msg = "Malformed certificate file " + certfilePath.native();
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700122 if (!isDryRun)
123 {
124 throw ConfigFile::Error(msg);
125 }
126 aggregateErrors(dryRunErrors, msg);
127 continue;
128 }
129
130 in.close();
131
132 const ConfigSection* privileges = 0;
133
134 try
135 {
136 privileges = &authIt->second.get_child("privileges");
137 }
138 catch (const std::runtime_error& error)
139 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600140 std::string msg = "No privileges section found for certificate file " +
141 certfile + " (" + id->getPublicKeyName().toUri() + ")";
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700142 if (!isDryRun)
143 {
144 throw ConfigFile::Error(msg);
145 }
146 aggregateErrors(dryRunErrors, msg);
147 continue;
148 }
149
150 if (privileges->begin() == privileges->end())
151 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600152 NFD_LOG_WARN("No privileges specified for certificate file " << certfile
153 << " (" << id->getPublicKeyName().toUri() << ")");
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700154 }
155
156 ConfigSection::const_iterator privIt;
157 for (privIt = privileges->begin(); privIt != privileges->end(); privIt++)
158 {
159 const std::string& privilegeName = privIt->first;
160 if (m_supportedPrivileges.find(privilegeName) != m_supportedPrivileges.end())
161 {
162 NFD_LOG_INFO("Giving privilege \"" << privilegeName
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600163 << "\" to identity " << id->getPublicKeyName());
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700164 if (!isDryRun)
165 {
166 const std::string regex = "^<localhost><nfd><" + privilegeName + ">";
167 m_validator.addInterestRule(regex, *id);
168 }
169 }
170 else
171 {
172 // Invalid configuration
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600173 std::string msg = "Invalid privilege \"" + privilegeName + "\" for certificate file " +
174 certfile + " (" + id->getPublicKeyName().toUri() + ")";
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700175 if (!isDryRun)
176 {
177 throw ConfigFile::Error(msg);
178 }
179 aggregateErrors(dryRunErrors, msg);
180 }
181 }
182 }
183
184 if (!dryRunErrors.str().empty())
185 {
186 throw ConfigFile::Error(dryRunErrors.str());
187 }
188}
189
190void
191CommandValidator::addSupportedPrivilege(const std::string& privilege)
192{
193 if (m_supportedPrivileges.find(privilege) != m_supportedPrivileges.end())
194 {
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600195 throw CommandValidator::Error("Duplicated privilege: " + privilege);
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700196 }
197 m_supportedPrivileges.insert(privilege);
198}
199
200} // namespace nfd