blob: cb0d4eb8ce04038abe8b4d21947d2290f649be7e [file] [log] [blame]
Vernon Mauery783dc072018-10-08 12:05:20 -07001#include <ipmid/api.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -07002#include <ipmid/utils.hpp>
Vernon Mauery783dc072018-10-08 12:05:20 -07003#include <ipmiwhitelist.hpp>
4#include <phosphor-logging/elog-errors.hpp>
5#include <phosphor-logging/log.hpp>
6#include <settings.hpp>
Patrick Williams6856f1b2023-09-01 16:10:07 -05007#include <xyz/openbmc_project/Common/error.hpp>
Vernon Mauery783dc072018-10-08 12:05:20 -07008#include <xyz/openbmc_project/Control/Security/RestrictionMode/server.hpp>
9
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050010#include <algorithm>
11#include <array>
12
Vernon Mauery783dc072018-10-08 12:05:20 -070013using namespace phosphor::logging;
Willy Tu523e2d12023-09-05 11:36:48 -070014using namespace sdbusplus::error::xyz::openbmc_project::common;
Vernon Mauery783dc072018-10-08 12:05:20 -070015
16namespace ipmi
17{
18
19// put the filter provider in an unnamed namespace
20namespace
21{
22
23/** @class WhitelistFilter
24 *
25 * Class that implements an IPMI message filter based
26 * on incoming interface and a restriction mode setting
27 */
28class WhitelistFilter
29{
30 public:
31 WhitelistFilter();
32 ~WhitelistFilter() = default;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050033 WhitelistFilter(const WhitelistFilter&) = delete;
Vernon Mauery783dc072018-10-08 12:05:20 -070034 WhitelistFilter(WhitelistFilter&&) = delete;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050035 WhitelistFilter& operator=(const WhitelistFilter&) = delete;
Vernon Mauery783dc072018-10-08 12:05:20 -070036 WhitelistFilter& operator=(WhitelistFilter&&) = delete;
37
38 private:
39 void postInit();
Kumar Thangavel902d90d2022-04-11 11:51:33 +053040 void cacheRestrictedMode(const std::vector<std::string>& devices);
41 void handleRestrictedModeChange(
Patrick Williams01d14602022-11-30 02:36:04 -060042 sdbusplus::message_t& m,
Kumar Thangavel902d90d2022-04-11 11:51:33 +053043 const std::map<std::string, size_t>& deviceList);
Vernon Mauery783dc072018-10-08 12:05:20 -070044 ipmi::Cc filterMessage(ipmi::message::Request::ptr request);
45
Kumar Thangavel902d90d2022-04-11 11:51:33 +053046 std::vector<bool> restrictedMode;
Vernon Mauery783dc072018-10-08 12:05:20 -070047 std::shared_ptr<sdbusplus::asio::connection> bus;
48 std::unique_ptr<settings::Objects> objects;
Patrick Williams5d82f472022-07-22 19:26:53 -050049 std::unique_ptr<sdbusplus::bus::match_t> modeChangeMatch;
Vernon Mauery783dc072018-10-08 12:05:20 -070050
51 static constexpr const char restrictionModeIntf[] =
52 "xyz.openbmc_project.Control.Security.RestrictionMode";
53};
54
55WhitelistFilter::WhitelistFilter()
56{
57 bus = getSdBus();
58
59 log<level::INFO>("Loading whitelist filter");
Vernon Mauery783dc072018-10-08 12:05:20 -070060 ipmi::registerFilter(ipmi::prioOpenBmcBase,
61 [this](ipmi::message::Request::ptr request) {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050062 return filterMessage(request);
63 });
Vernon Mauery783dc072018-10-08 12:05:20 -070064
65 // wait until io->run is going to fetch RestrictionMode
66 post_work([this]() { postInit(); });
67}
68
Kumar Thangavel902d90d2022-04-11 11:51:33 +053069/** @brief Get RestrictionMode of the devices which has RestrictionMode support
70 * enabled
71 * @param[in] devices - vector of devices object path
72 * @returns void.
73 */
74
75void WhitelistFilter::cacheRestrictedMode(
76 const std::vector<std::string>& devices)
Vernon Mauery783dc072018-10-08 12:05:20 -070077{
Willy Tu523e2d12023-09-05 11:36:48 -070078 using namespace sdbusplus::server::xyz::openbmc_project::control::security;
Vernon Mauery783dc072018-10-08 12:05:20 -070079 std::string restrictionModeSetting;
80 std::string restrictionModeService;
Kumar Thangavel902d90d2022-04-11 11:51:33 +053081
82 for (auto& dev : devices)
Vernon Mauery783dc072018-10-08 12:05:20 -070083 {
Kumar Thangavel902d90d2022-04-11 11:51:33 +053084 try
85 {
86 restrictionModeSetting = dev;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050087 restrictionModeService = objects->service(restrictionModeSetting,
88 restrictionModeIntf);
Kumar Thangavel902d90d2022-04-11 11:51:33 +053089 }
90 catch (const std::out_of_range& e)
91 {
92 log<level::ERR>(
93 "Could not look up restriction mode interface from cache");
94 return;
95 }
96
97 bus->async_method_call(
98 [this, index = std::distance(&*std::begin(devices), &dev)](
99 boost::system::error_code ec, ipmi::Value v) {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500100 if (ec)
101 {
102 log<level::ERR>("Error in RestrictionMode Get");
103 // Fail-safe to true.
104 restrictedMode[index] = true;
105 return;
106 }
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530107
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500108 auto mode = std::get<std::string>(v);
109 auto restrictionMode =
110 RestrictionMode::convertModesFromString(mode);
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530111
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500112 bool restrictMode =
113 (restrictionMode == RestrictionMode::Modes::Whitelist);
114 restrictedMode.emplace_back(restrictMode);
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530115
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500116 log<level::INFO>((restrictMode ? "Set restrictedMode = true"
117 : "Set restrictedMode = false"));
Patrick Williams369824e2023-10-20 11:18:23 -0500118 },
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530119 restrictionModeService, restrictionModeSetting,
120 "org.freedesktop.DBus.Properties", "Get", restrictionModeIntf,
121 "RestrictionMode");
Vernon Mauery783dc072018-10-08 12:05:20 -0700122 }
Vernon Mauery783dc072018-10-08 12:05:20 -0700123}
124
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530125/** @brief Update RestrictionMode if any changes in RestrictionMode
126 * @param[in] m - sdbusplus message. Using this to get Updated Mode dbus path
127 * @param[in] deviceList - map to store devices path and their index
128 * @returns void.
129 */
130
131void WhitelistFilter::handleRestrictedModeChange(
132 sdbusplus::message_t& m, const std::map<std::string, size_t>& deviceList)
Vernon Mauery783dc072018-10-08 12:05:20 -0700133{
Willy Tu523e2d12023-09-05 11:36:48 -0700134 using namespace sdbusplus::server::xyz::openbmc_project::control::security;
Richard Marian Thomaiyar57bff012019-04-12 22:32:21 +0530135 std::string intf;
136 std::vector<std::pair<std::string, ipmi::Value>> propertyList;
137 m.read(intf, propertyList);
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530138
139 std::string path = m.get_path();
140 size_t hostId = 0;
141 auto it = deviceList.find(path);
142
143 if (it == deviceList.end())
144 {
145 log<level::ERR>("Key not found in deviceList ");
146 }
147 else
148 {
149 hostId = it->second;
150 }
151
Richard Marian Thomaiyar57bff012019-04-12 22:32:21 +0530152 for (const auto& property : propertyList)
153 {
154 if (property.first == "RestrictionMode")
155 {
156 RestrictionMode::Modes restrictionMode =
157 RestrictionMode::convertModesFromString(
158 std::get<std::string>(property.second));
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530159 bool restrictMode =
Richard Marian Thomaiyar57bff012019-04-12 22:32:21 +0530160 (restrictionMode == RestrictionMode::Modes::Whitelist);
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530161 restrictedMode[hostId] = restrictMode;
162 log<level::INFO>((restrictMode ? "Updated restrictedMode = true"
163 : "Updated restrictedMode = false"));
Richard Marian Thomaiyar57bff012019-04-12 22:32:21 +0530164 }
165 }
Vernon Mauery783dc072018-10-08 12:05:20 -0700166}
167
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530168/** @brief Get and Update RestrictionModes of supported devices
169 * @param[in] void
170 * @returns void.
171 */
172
Vernon Mauery783dc072018-10-08 12:05:20 -0700173void WhitelistFilter::postInit()
174{
175 objects = std::make_unique<settings::Objects>(
176 *bus, std::vector<settings::Interface>({restrictionModeIntf}));
177 if (!objects)
178 {
179 log<level::ERR>(
180 "Failed to create settings object; defaulting to restricted mode");
181 return;
182 }
183
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530184 std::vector<std::string> devices;
Vernon Mauery783dc072018-10-08 12:05:20 -0700185 try
186 {
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530187 devices = objects->map.at(restrictionModeIntf);
Vernon Mauery783dc072018-10-08 12:05:20 -0700188 }
189 catch (const std::out_of_range& e)
190 {
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530191 log<level::ERR>(
192 "Could not look up restriction mode interface from cache");
Vernon Mauery783dc072018-10-08 12:05:20 -0700193 return;
194 }
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530195
196 // Initialize restricted mode
197 cacheRestrictedMode(devices);
198 // Wait for changes on Restricted mode
199 std::map<std::string, size_t> deviceList;
200
201 for (size_t index = 0; index < devices.size(); index++)
202 {
203 deviceList.emplace(devices[index], index);
204 }
205
206 std::string filterStr;
207 std::string devicesDbusPath{"/xyz/openbmc_project/control"};
208
209 filterStr = sdbusplus::bus::match::rules::propertiesChangedNamespace(
210 devicesDbusPath, restrictionModeIntf);
211
Patrick Williams5d82f472022-07-22 19:26:53 -0500212 modeChangeMatch = std::make_unique<sdbusplus::bus::match_t>(
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530213 *bus, filterStr, [this, deviceList](sdbusplus::message_t& m) {
Patrick Williams369824e2023-10-20 11:18:23 -0500214 handleRestrictedModeChange(m, deviceList);
215 });
Vernon Mauery783dc072018-10-08 12:05:20 -0700216}
217
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530218/** @brief Filter IPMI messages with RestrictedMode
219 * @param[in] request - IPMI messahe request
220 * @returns IPMI completion code success or error.
221 */
222
Vernon Mauery783dc072018-10-08 12:05:20 -0700223ipmi::Cc WhitelistFilter::filterMessage(ipmi::message::Request::ptr request)
224{
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530225 /* Getting hostIdx for all IPMI devices like hosts, debugcard and other
226 devices from ipmi::message::Request and call postInit() to get the
227 restriction mode for all the IPMI commands */
228
229 size_t hostIdx = request->ctx->hostIdx;
230
231 if (request->ctx->channel == ipmi::channelSystemIface &&
232 restrictedMode[hostIdx])
Vernon Mauery783dc072018-10-08 12:05:20 -0700233 {
234 if (!std::binary_search(
235 whitelist.cbegin(), whitelist.cend(),
236 std::make_pair(request->ctx->netFn, request->ctx->cmd)))
237 {
238 log<level::ERR>("Net function not whitelisted",
239 entry("NETFN=0x%X", int(request->ctx->netFn)),
240 entry("CMD=0x%X", int(request->ctx->cmd)));
Kumar Thangavel902d90d2022-04-11 11:51:33 +0530241
Vernon Mauery783dc072018-10-08 12:05:20 -0700242 return ipmi::ccInsufficientPrivilege;
243 }
244 }
245 return ipmi::ccSuccess;
246}
247
248// instantiate the WhitelistFilter when this shared object is loaded
249WhitelistFilter whitelistFilter;
250
251} // namespace
252
253} // namespace ipmi