blob: 1a7c2665417a6bccf51b04626be376e9777976b8 [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>
George Liu7b7f25f2022-07-04 17:07:32 +080010#include <phosphor-logging/lg2.hpp>
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +000011
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{
18
Vernon Mauery9e801a22018-10-12 13:20:49 -070019std::vector<uint8_t>
20 setSessionPrivilegeLevel(const std::vector<uint8_t>& inPayload,
Vernon Mauery41ff9b52021-06-11 11:37:40 -070021 std::shared_ptr<message::Handler>& handler)
Tom Joseph9662c3a2016-12-06 17:52:16 +053022{
Vernon Mauery9e801a22018-10-12 13:20:49 -070023 auto request =
24 reinterpret_cast<const SetSessionPrivLevelReq*>(inPayload.data());
Zhikui Ren2b1edef2020-07-24 14:32:13 -070025 if (inPayload.size() != sizeof(*request))
26 {
27 std::vector<uint8_t> errorPayload{IPMI_CC_REQ_DATA_LEN_INVALID};
28 return errorPayload;
29 }
Jayaprakash Mutyala58196662021-10-06 22:33:34 +000030 if (request->reserved != 0)
31 {
32 std::vector<uint8_t> errorPayload{IPMI_CC_INVALID_FIELD_REQUEST};
33 return errorPayload;
34 }
Zhikui Ren2b1edef2020-07-24 14:32:13 -070035
36 std::vector<uint8_t> outPayload(sizeof(SetSessionPrivLevelResp));
Vernon Mauery9e801a22018-10-12 13:20:49 -070037 auto response =
38 reinterpret_cast<SetSessionPrivLevelResp*>(outPayload.data());
Tom Joseph9662c3a2016-12-06 17:52:16 +053039 response->completionCode = IPMI_CC_OK;
40 uint8_t reqPrivilegeLevel = request->reqPrivLevel;
41
Vernon Mauery41ff9b52021-06-11 11:37:40 -070042 auto session = session::Manager::get().getSession(handler->sessionID);
Tom Joseph9662c3a2016-12-06 17:52:16 +053043
44 if (reqPrivilegeLevel == 0) // Just return present privilege level
45 {
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053046 response->newPrivLevel = session->currentPrivilege();
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053047 return outPayload;
Tom Joseph9662c3a2016-12-06 17:52:16 +053048 }
Jayaprakash Mutyala58196662021-10-06 22:33:34 +000049 if (reqPrivilegeLevel ==
50 static_cast<uint8_t>(session::Privilege::CALLBACK) ||
51 reqPrivilegeLevel > static_cast<uint8_t>(session::Privilege::OEM))
52 {
53 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
54 return outPayload;
55 }
56
Tom Joseph4021b1f2019-02-12 10:10:12 +053057 if (reqPrivilegeLevel > (static_cast<uint8_t>(session->reqMaxPrivLevel) &
58 session::reqMaxPrivMask))
Tom Joseph9662c3a2016-12-06 17:52:16 +053059 {
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053060 // Requested level exceeds Channel and/or User Privilege Limit
61 response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
62 return outPayload;
63 }
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053064 // Use the minimum privilege of user or channel
65 uint8_t minPriv = 0;
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053066 if (session->sessionChannelAccess.privLimit <
67 session->sessionUserPrivAccess.privilege)
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053068 {
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053069 minPriv = session->sessionChannelAccess.privLimit;
Tom Joseph9662c3a2016-12-06 17:52:16 +053070 }
71 else
72 {
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053073 minPriv = session->sessionUserPrivAccess.privilege;
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053074 }
75 if (reqPrivilegeLevel > minPriv)
76 {
Tom Joseph9662c3a2016-12-06 17:52:16 +053077 // Requested level exceeds Channel and/or User Privilege Limit
78 response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
79 }
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053080 else
81 {
82 // update current privilege of the session.
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053083 session->currentPrivilege(static_cast<uint8_t>(reqPrivilegeLevel));
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053084 response->newPrivLevel = reqPrivilegeLevel;
85 }
86
Tom Joseph9662c3a2016-12-06 17:52:16 +053087 return outPayload;
88}
89
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +000090/**
91 * @brief set the session state as teardown
92 *
93 * This function is to set the session state to tear down in progress if the
94 * state is active.
95 *
96 * @param[in] busp - Dbus obj
97 * @param[in] service - service name
98 * @param[in] obj - object path
99 *
100 * @return success completion code if it sets the session state to
101 * tearDownInProgress else return the corresponding error completion code.
102 **/
103uint8_t setSessionState(std::shared_ptr<sdbusplus::asio::connection>& busp,
104 const std::string& service, const std::string& obj)
105{
106 try
107 {
108 uint8_t sessionState = std::get<uint8_t>(ipmi::getDbusProperty(
109 *busp, service, obj, session::sessionIntf, "State"));
110
111 if (sessionState == static_cast<uint8_t>(session::State::active))
112 {
113 ipmi::setDbusProperty(
114 *busp, service, obj, session::sessionIntf, "State",
115 static_cast<uint8_t>(session::State::tearDownInProgress));
116 return ipmi::ccSuccess;
117 }
118 }
Patrick Williams12d199b2021-10-06 12:36:48 -0500119 catch (const std::exception& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000120 {
George Liu7b7f25f2022-07-04 17:07:32 +0800121 lg2::error(
122 "Failed in getting session state property: {SERVICE}, {PATH}, {INTERFACE}",
123 "SERVICE", service, "PATH", obj, "INTERFACE", session::sessionIntf);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000124 return ipmi::ccUnspecifiedError;
125 }
126
127 return ipmi::ccInvalidFieldRequest;
128}
129
130uint8_t closeOtherNetInstanceSession(const uint32_t reqSessionId,
131 const uint8_t reqSessionHandle,
132 const uint8_t currentSessionPriv)
133{
134 auto busp = getSdBus();
135
136 try
137 {
138 ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
139 *busp, session::sessionManagerRootPath, session::sessionIntf);
140
141 for (auto& objectTreeItr : objectTree)
142 {
143 const std::string obj = objectTreeItr.first;
144
145 if (isSessionObjectMatched(obj, reqSessionId, reqSessionHandle))
146 {
147 auto& serviceMap = objectTreeItr.second;
148
149 if (serviceMap.size() != 1)
150 {
151 return ipmi::ccUnspecifiedError;
152 }
153
154 auto itr = serviceMap.begin();
155 const std::string service = itr->first;
Patrick Williams099fb092023-05-10 07:50:31 -0500156 uint8_t closeSessionPriv = std::get<uint8_t>(
157 ipmi::getDbusProperty(*busp, service, obj,
158 session::sessionIntf,
159 "CurrentPrivilege"));
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000160
161 if (currentSessionPriv < closeSessionPriv)
162 {
163 return ipmi::ccInsufficientPrivilege;
164 }
165 return setSessionState(busp, service, obj);
166 }
167 }
168 }
Patrick Williams0a590622022-07-22 19:26:53 -0500169 catch (const sdbusplus::exception_t& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000170 {
George Liu7b7f25f2022-07-04 17:07:32 +0800171 lg2::error(
172 "Failed to fetch object from dbus, interface: {INTERFACE}, error: {ERROR}",
173 "INTERFACE", session::sessionIntf, "ERROR", e);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000174 return ipmi::ccUnspecifiedError;
175 }
176
177 return ipmi::ccInvalidFieldRequest;
178}
179
180uint8_t closeMyNetInstanceSession(uint32_t reqSessionId,
181 uint8_t reqSessionHandle,
182 const uint8_t currentSessionPriv)
183{
184 bool status = false;
185
186 try
187 {
188 if (reqSessionId == session::sessionZero)
189 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700190 reqSessionId = session::Manager::get().getSessionIDbyHandle(
191 reqSessionHandle & session::multiIntfaceSessionHandleMask);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000192 if (!reqSessionId)
193 {
194 return session::ccInvalidSessionHandle;
195 }
196 }
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000197 }
198 catch (const std::exception& e)
199 {
George Liu7b7f25f2022-07-04 17:07:32 +0800200 lg2::error(
201 "Failed to get session manager instance or sessionID by sessionHandle: {ERROR}",
202 "ERROR", e);
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000203 return session::ccInvalidSessionHandle;
204 }
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000205
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000206 try
207 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000208 auto closeSessionInstance =
Vernon Mauery2085ae02021-06-10 11:51:00 -0700209 session::Manager::get().getSession(reqSessionId);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000210 uint8_t closeSessionPriv = closeSessionInstance->currentPrivilege();
211
212 if (currentSessionPriv < closeSessionPriv)
213 {
214 return ipmi::ccInsufficientPrivilege;
215 }
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000216 }
217 catch (const std::exception& e)
218 {
George Liu7b7f25f2022-07-04 17:07:32 +0800219 lg2::error(
220 "Failed to get session manager instance or sessionID: {ERROR}",
221 "ERROR", e);
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000222 return session::ccInvalidSessionId;
223 }
224
225 try
226 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700227 status = session::Manager::get().stopSession(reqSessionId);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000228
229 if (!status)
230 {
231 return session::ccInvalidSessionId;
232 }
233 }
Patrick Williams12d199b2021-10-06 12:36:48 -0500234 catch (const std::exception& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000235 {
George Liu7b7f25f2022-07-04 17:07:32 +0800236 lg2::error(
237 "Failed to get session manager instance or stop session: {ERROR}",
238 "ERROR", e);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000239 return ipmi::ccUnspecifiedError;
240 }
241
242 return ipmi::ccSuccess;
243}
244
Tom Joseph18a45e92017-04-11 11:30:44 +0530245std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
Vernon Mauery41ff9b52021-06-11 11:37:40 -0700246 std::shared_ptr<message::Handler>& handler)
Tom Joseph9662c3a2016-12-06 17:52:16 +0530247{
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700248 // minimum inPayload size is reqSessionId (uint32_t)
249 // maximum inPayload size is struct CloseSessionRequest
250 if (inPayload.size() != sizeof(uint32_t) &&
251 inPayload.size() != sizeof(CloseSessionRequest))
252 {
253 std::vector<uint8_t> errorPayload{IPMI_CC_REQ_DATA_LEN_INVALID};
254 return errorPayload;
255 }
256
Vernon Mauery9e801a22018-10-12 13:20:49 -0700257 auto request =
258 reinterpret_cast<const CloseSessionRequest*>(inPayload.data());
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700259
260 std::vector<uint8_t> outPayload(sizeof(CloseSessionResponse));
Tom Joseph9662c3a2016-12-06 17:52:16 +0530261 auto response = reinterpret_cast<CloseSessionResponse*>(outPayload.data());
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000262 uint32_t reqSessionId = request->sessionID;
263 uint8_t ipmiNetworkInstance = 0;
264 uint8_t currentSessionPriv = 0;
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700265 uint8_t reqSessionHandle = session::invalidSessionHandle;
266
267 if (inPayload.size() == sizeof(CloseSessionRequest))
268 {
269 reqSessionHandle = request->sessionHandle;
270 }
Tom Joseph9662c3a2016-12-06 17:52:16 +0530271
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000272 if (reqSessionId == session::sessionZero &&
273 reqSessionHandle == session::invalidSessionHandle)
Tom Joseph9662c3a2016-12-06 17:52:16 +0530274 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000275 response->completionCode = session::ccInvalidSessionHandle;
276 return outPayload;
277 }
278
279 if (inPayload.size() == sizeof(reqSessionId) &&
280 reqSessionId == session::sessionZero)
281 {
282 response->completionCode = session::ccInvalidSessionId;
283 return outPayload;
284 }
285
286 if (reqSessionId != session::sessionZero &&
287 inPayload.size() != sizeof(reqSessionId))
288 {
289 response->completionCode = ipmi::ccInvalidFieldRequest;
290 return outPayload;
291 }
292
293 try
294 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700295 ipmiNetworkInstance = session::Manager::get().getNetworkInstance();
296 auto currentSession =
Vernon Mauery41ff9b52021-06-11 11:37:40 -0700297 session::Manager::get().getSession(handler->sessionID);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000298 currentSessionPriv = currentSession->currentPrivilege();
299 }
Patrick Williams0a590622022-07-22 19:26:53 -0500300 catch (const sdbusplus::exception_t& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000301 {
George Liu7b7f25f2022-07-04 17:07:32 +0800302 lg2::error(
303 "Failed to fetch object from dbus, interface: {INTERFACE}, error: {ERROR}",
304 "INTERFACE", session::sessionIntf, "ERROR", e);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000305 response->completionCode = ipmi::ccUnspecifiedError;
306 return outPayload;
307 }
308
309 if (reqSessionId >> myNetInstanceSessionIdShiftMask ==
310 ipmiNetworkInstance ||
311 (reqSessionId == session::sessionZero &&
312 (reqSessionHandle >> myNetInstanceSessionHandleShiftMask ==
313 ipmiNetworkInstance)))
314 {
315 response->completionCode = closeMyNetInstanceSession(
316 reqSessionId, reqSessionHandle, currentSessionPriv);
Vernon Mauery2085ae02021-06-10 11:51:00 -0700317 session::Manager::get().scheduleSessionCleaner(100us);
Tom Joseph9662c3a2016-12-06 17:52:16 +0530318 }
319 else
320 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000321 response->completionCode = closeOtherNetInstanceSession(
322 reqSessionId, reqSessionHandle, currentSessionPriv);
Tom Joseph9662c3a2016-12-06 17:52:16 +0530323 }
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000324
Tom Joseph9662c3a2016-12-06 17:52:16 +0530325 return outPayload;
326}
327
328} // namespace command