blob: 8a4014af80b721029365f6e288f5ad6b434eee45 [file] [log] [blame]
Tom Joseph9662c3a2016-12-06 17:52:16 +05301#include "session_cmds.hpp"
2
Tom Joseph9662c3a2016-12-06 17:52:16 +05303#include "endian.hpp"
Vernon Mauery2085ae02021-06-10 11:51:00 -07004#include "sessions_manager.hpp"
Vernon Mauery9e801a22018-10-12 13:20:49 -07005
William A. Kennington III4f09eae2019-02-12 17:10:35 -08006#include <ipmid/api.h>
Tom Joseph9662c3a2016-12-06 17:52:16 +05307
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +00008#include <ipmid/sessionhelper.hpp>
9#include <ipmid/utils.hpp>
10#include <phosphor-logging/log.hpp>
11
George Liubc8958f2022-07-04 09:29:49 +080012#include <chrono>
13
Vernon Maueryecc8efa2021-06-12 12:52:23 -070014using namespace std::chrono_literals;
15
Tom Joseph9662c3a2016-12-06 17:52:16 +053016namespace command
17{
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +000018using namespace phosphor::logging;
Tom Joseph9662c3a2016-12-06 17:52:16 +053019
Vernon Mauery9e801a22018-10-12 13:20:49 -070020std::vector<uint8_t>
21 setSessionPrivilegeLevel(const std::vector<uint8_t>& inPayload,
Vernon Mauery41ff9b52021-06-11 11:37:40 -070022 std::shared_ptr<message::Handler>& handler)
Tom Joseph9662c3a2016-12-06 17:52:16 +053023{
Vernon Mauery9e801a22018-10-12 13:20:49 -070024 auto request =
25 reinterpret_cast<const SetSessionPrivLevelReq*>(inPayload.data());
Zhikui Ren2b1edef2020-07-24 14:32:13 -070026 if (inPayload.size() != sizeof(*request))
27 {
28 std::vector<uint8_t> errorPayload{IPMI_CC_REQ_DATA_LEN_INVALID};
29 return errorPayload;
30 }
Jayaprakash Mutyala58196662021-10-06 22:33:34 +000031 if (request->reserved != 0)
32 {
33 std::vector<uint8_t> errorPayload{IPMI_CC_INVALID_FIELD_REQUEST};
34 return errorPayload;
35 }
Zhikui Ren2b1edef2020-07-24 14:32:13 -070036
37 std::vector<uint8_t> outPayload(sizeof(SetSessionPrivLevelResp));
Vernon Mauery9e801a22018-10-12 13:20:49 -070038 auto response =
39 reinterpret_cast<SetSessionPrivLevelResp*>(outPayload.data());
Tom Joseph9662c3a2016-12-06 17:52:16 +053040 response->completionCode = IPMI_CC_OK;
41 uint8_t reqPrivilegeLevel = request->reqPrivLevel;
42
Vernon Mauery41ff9b52021-06-11 11:37:40 -070043 auto session = session::Manager::get().getSession(handler->sessionID);
Tom Joseph9662c3a2016-12-06 17:52:16 +053044
45 if (reqPrivilegeLevel == 0) // Just return present privilege level
46 {
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053047 response->newPrivLevel = session->currentPrivilege();
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053048 return outPayload;
Tom Joseph9662c3a2016-12-06 17:52:16 +053049 }
Jayaprakash Mutyala58196662021-10-06 22:33:34 +000050 if (reqPrivilegeLevel ==
51 static_cast<uint8_t>(session::Privilege::CALLBACK) ||
52 reqPrivilegeLevel > static_cast<uint8_t>(session::Privilege::OEM))
53 {
54 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
55 return outPayload;
56 }
57
Tom Joseph4021b1f2019-02-12 10:10:12 +053058 if (reqPrivilegeLevel > (static_cast<uint8_t>(session->reqMaxPrivLevel) &
59 session::reqMaxPrivMask))
Tom Joseph9662c3a2016-12-06 17:52:16 +053060 {
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053061 // Requested level exceeds Channel and/or User Privilege Limit
62 response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
63 return outPayload;
64 }
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053065 // Use the minimum privilege of user or channel
66 uint8_t minPriv = 0;
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053067 if (session->sessionChannelAccess.privLimit <
68 session->sessionUserPrivAccess.privilege)
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053069 {
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053070 minPriv = session->sessionChannelAccess.privLimit;
Tom Joseph9662c3a2016-12-06 17:52:16 +053071 }
72 else
73 {
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053074 minPriv = session->sessionUserPrivAccess.privilege;
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053075 }
76 if (reqPrivilegeLevel > minPriv)
77 {
Tom Joseph9662c3a2016-12-06 17:52:16 +053078 // Requested level exceeds Channel and/or User Privilege Limit
79 response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
80 }
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053081 else
82 {
83 // update current privilege of the session.
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053084 session->currentPrivilege(static_cast<uint8_t>(reqPrivilegeLevel));
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053085 response->newPrivLevel = reqPrivilegeLevel;
86 }
87
Tom Joseph9662c3a2016-12-06 17:52:16 +053088 return outPayload;
89}
90
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +000091/**
92 * @brief set the session state as teardown
93 *
94 * This function is to set the session state to tear down in progress if the
95 * state is active.
96 *
97 * @param[in] busp - Dbus obj
98 * @param[in] service - service name
99 * @param[in] obj - object path
100 *
101 * @return success completion code if it sets the session state to
102 * tearDownInProgress else return the corresponding error completion code.
103 **/
104uint8_t setSessionState(std::shared_ptr<sdbusplus::asio::connection>& busp,
105 const std::string& service, const std::string& obj)
106{
107 try
108 {
109 uint8_t sessionState = std::get<uint8_t>(ipmi::getDbusProperty(
110 *busp, service, obj, session::sessionIntf, "State"));
111
112 if (sessionState == static_cast<uint8_t>(session::State::active))
113 {
114 ipmi::setDbusProperty(
115 *busp, service, obj, session::sessionIntf, "State",
116 static_cast<uint8_t>(session::State::tearDownInProgress));
117 return ipmi::ccSuccess;
118 }
119 }
Patrick Williams12d199b2021-10-06 12:36:48 -0500120 catch (const std::exception& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000121 {
122 log<level::ERR>("Failed in getting session state property",
123 entry("service=%s", service.c_str()),
124 entry("object path=%s", obj.c_str()),
125 entry("interface=%s", session::sessionIntf));
126 return ipmi::ccUnspecifiedError;
127 }
128
129 return ipmi::ccInvalidFieldRequest;
130}
131
132uint8_t closeOtherNetInstanceSession(const uint32_t reqSessionId,
133 const uint8_t reqSessionHandle,
134 const uint8_t currentSessionPriv)
135{
136 auto busp = getSdBus();
137
138 try
139 {
140 ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
141 *busp, session::sessionManagerRootPath, session::sessionIntf);
142
143 for (auto& objectTreeItr : objectTree)
144 {
145 const std::string obj = objectTreeItr.first;
146
147 if (isSessionObjectMatched(obj, reqSessionId, reqSessionHandle))
148 {
149 auto& serviceMap = objectTreeItr.second;
150
151 if (serviceMap.size() != 1)
152 {
153 return ipmi::ccUnspecifiedError;
154 }
155
156 auto itr = serviceMap.begin();
157 const std::string service = itr->first;
158 uint8_t closeSessionPriv =
159 std::get<uint8_t>(ipmi::getDbusProperty(
160 *busp, service, obj, session::sessionIntf,
161 "CurrentPrivilege"));
162
163 if (currentSessionPriv < closeSessionPriv)
164 {
165 return ipmi::ccInsufficientPrivilege;
166 }
167 return setSessionState(busp, service, obj);
168 }
169 }
170 }
Patrick Williams0a590622022-07-22 19:26:53 -0500171 catch (const sdbusplus::exception_t& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000172 {
173 log<level::ERR>("Failed to fetch object from dbus",
174 entry("INTERFACE=%s", session::sessionIntf),
175 entry("ERRMSG=%s", e.what()));
176 return ipmi::ccUnspecifiedError;
177 }
178
179 return ipmi::ccInvalidFieldRequest;
180}
181
182uint8_t closeMyNetInstanceSession(uint32_t reqSessionId,
183 uint8_t reqSessionHandle,
184 const uint8_t currentSessionPriv)
185{
186 bool status = false;
187
188 try
189 {
190 if (reqSessionId == session::sessionZero)
191 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700192 reqSessionId = session::Manager::get().getSessionIDbyHandle(
193 reqSessionHandle & session::multiIntfaceSessionHandleMask);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000194 if (!reqSessionId)
195 {
196 return session::ccInvalidSessionHandle;
197 }
198 }
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000199 }
200 catch (const std::exception& e)
201 {
202 log<level::ERR>("Failed to get session manager instance or sessionID "
203 "by sessionHandle",
204 entry("ERRMSG=%s", e.what()));
205 return session::ccInvalidSessionHandle;
206 }
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000207
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000208 try
209 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000210 auto closeSessionInstance =
Vernon Mauery2085ae02021-06-10 11:51:00 -0700211 session::Manager::get().getSession(reqSessionId);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000212 uint8_t closeSessionPriv = closeSessionInstance->currentPrivilege();
213
214 if (currentSessionPriv < closeSessionPriv)
215 {
216 return ipmi::ccInsufficientPrivilege;
217 }
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000218 }
219 catch (const std::exception& e)
220 {
221 log<level::ERR>("Failed to get session manager instance or sessionID",
222 entry("ERRMSG=%s", e.what()));
223 return session::ccInvalidSessionId;
224 }
225
226 try
227 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700228 status = session::Manager::get().stopSession(reqSessionId);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000229
230 if (!status)
231 {
232 return session::ccInvalidSessionId;
233 }
234 }
Patrick Williams12d199b2021-10-06 12:36:48 -0500235 catch (const std::exception& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000236 {
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000237 log<level::ERR>(
238 "Failed to get session manager instance or stop session",
239 entry("ERRMSG=%s", e.what()));
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000240 return ipmi::ccUnspecifiedError;
241 }
242
243 return ipmi::ccSuccess;
244}
245
Tom Joseph18a45e92017-04-11 11:30:44 +0530246std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
Vernon Mauery41ff9b52021-06-11 11:37:40 -0700247 std::shared_ptr<message::Handler>& handler)
Tom Joseph9662c3a2016-12-06 17:52:16 +0530248{
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700249 // minimum inPayload size is reqSessionId (uint32_t)
250 // maximum inPayload size is struct CloseSessionRequest
251 if (inPayload.size() != sizeof(uint32_t) &&
252 inPayload.size() != sizeof(CloseSessionRequest))
253 {
254 std::vector<uint8_t> errorPayload{IPMI_CC_REQ_DATA_LEN_INVALID};
255 return errorPayload;
256 }
257
Vernon Mauery9e801a22018-10-12 13:20:49 -0700258 auto request =
259 reinterpret_cast<const CloseSessionRequest*>(inPayload.data());
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700260
261 std::vector<uint8_t> outPayload(sizeof(CloseSessionResponse));
Tom Joseph9662c3a2016-12-06 17:52:16 +0530262 auto response = reinterpret_cast<CloseSessionResponse*>(outPayload.data());
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000263 uint32_t reqSessionId = request->sessionID;
264 uint8_t ipmiNetworkInstance = 0;
265 uint8_t currentSessionPriv = 0;
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700266 uint8_t reqSessionHandle = session::invalidSessionHandle;
267
268 if (inPayload.size() == sizeof(CloseSessionRequest))
269 {
270 reqSessionHandle = request->sessionHandle;
271 }
Tom Joseph9662c3a2016-12-06 17:52:16 +0530272
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000273 if (reqSessionId == session::sessionZero &&
274 reqSessionHandle == session::invalidSessionHandle)
Tom Joseph9662c3a2016-12-06 17:52:16 +0530275 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000276 response->completionCode = session::ccInvalidSessionHandle;
277 return outPayload;
278 }
279
280 if (inPayload.size() == sizeof(reqSessionId) &&
281 reqSessionId == session::sessionZero)
282 {
283 response->completionCode = session::ccInvalidSessionId;
284 return outPayload;
285 }
286
287 if (reqSessionId != session::sessionZero &&
288 inPayload.size() != sizeof(reqSessionId))
289 {
290 response->completionCode = ipmi::ccInvalidFieldRequest;
291 return outPayload;
292 }
293
294 try
295 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700296 ipmiNetworkInstance = session::Manager::get().getNetworkInstance();
297 auto currentSession =
Vernon Mauery41ff9b52021-06-11 11:37:40 -0700298 session::Manager::get().getSession(handler->sessionID);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000299 currentSessionPriv = currentSession->currentPrivilege();
300 }
Patrick Williams0a590622022-07-22 19:26:53 -0500301 catch (const sdbusplus::exception_t& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000302 {
303 log<level::ERR>("Failed to fetch object from dbus",
304 entry("INTERFACE=%s", session::sessionIntf),
305 entry("ERRMSG=%s", e.what()));
306 response->completionCode = ipmi::ccUnspecifiedError;
307 return outPayload;
308 }
309
310 if (reqSessionId >> myNetInstanceSessionIdShiftMask ==
311 ipmiNetworkInstance ||
312 (reqSessionId == session::sessionZero &&
313 (reqSessionHandle >> myNetInstanceSessionHandleShiftMask ==
314 ipmiNetworkInstance)))
315 {
316 response->completionCode = closeMyNetInstanceSession(
317 reqSessionId, reqSessionHandle, currentSessionPriv);
Vernon Mauery2085ae02021-06-10 11:51:00 -0700318 session::Manager::get().scheduleSessionCleaner(100us);
Tom Joseph9662c3a2016-12-06 17:52:16 +0530319 }
320 else
321 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000322 response->completionCode = closeOtherNetInstanceSession(
323 reqSessionId, reqSessionHandle, currentSessionPriv);
Tom Joseph9662c3a2016-12-06 17:52:16 +0530324 }
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000325
Tom Joseph9662c3a2016-12-06 17:52:16 +0530326 return outPayload;
327}
328
329} // namespace command