blob: da34c3c17b1479e6797249a6d02ef569631396d1 [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
Vernon Maueryecc8efa2021-06-12 12:52:23 -07008#include <chrono>
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +00009#include <ipmid/sessionhelper.hpp>
10#include <ipmid/utils.hpp>
11#include <phosphor-logging/log.hpp>
12
Vernon Maueryecc8efa2021-06-12 12:52:23 -070013using namespace std::chrono_literals;
14
Tom Joseph9662c3a2016-12-06 17:52:16 +053015namespace command
16{
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +000017using namespace phosphor::logging;
Tom Joseph9662c3a2016-12-06 17:52:16 +053018
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 {
121 log<level::ERR>("Failed in getting session state property",
122 entry("service=%s", service.c_str()),
123 entry("object path=%s", obj.c_str()),
124 entry("interface=%s", session::sessionIntf));
125 return ipmi::ccUnspecifiedError;
126 }
127
128 return ipmi::ccInvalidFieldRequest;
129}
130
131uint8_t closeOtherNetInstanceSession(const uint32_t reqSessionId,
132 const uint8_t reqSessionHandle,
133 const uint8_t currentSessionPriv)
134{
135 auto busp = getSdBus();
136
137 try
138 {
139 ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
140 *busp, session::sessionManagerRootPath, session::sessionIntf);
141
142 for (auto& objectTreeItr : objectTree)
143 {
144 const std::string obj = objectTreeItr.first;
145
146 if (isSessionObjectMatched(obj, reqSessionId, reqSessionHandle))
147 {
148 auto& serviceMap = objectTreeItr.second;
149
150 if (serviceMap.size() != 1)
151 {
152 return ipmi::ccUnspecifiedError;
153 }
154
155 auto itr = serviceMap.begin();
156 const std::string service = itr->first;
157 uint8_t closeSessionPriv =
158 std::get<uint8_t>(ipmi::getDbusProperty(
159 *busp, service, obj, session::sessionIntf,
160 "CurrentPrivilege"));
161
162 if (currentSessionPriv < closeSessionPriv)
163 {
164 return ipmi::ccInsufficientPrivilege;
165 }
166 return setSessionState(busp, service, obj);
167 }
168 }
169 }
Patrick Williams12d199b2021-10-06 12:36:48 -0500170 catch (const sdbusplus::exception::exception& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000171 {
172 log<level::ERR>("Failed to fetch object from dbus",
173 entry("INTERFACE=%s", session::sessionIntf),
174 entry("ERRMSG=%s", e.what()));
175 return ipmi::ccUnspecifiedError;
176 }
177
178 return ipmi::ccInvalidFieldRequest;
179}
180
181uint8_t closeMyNetInstanceSession(uint32_t reqSessionId,
182 uint8_t reqSessionHandle,
183 const uint8_t currentSessionPriv)
184{
185 bool status = false;
186
187 try
188 {
189 if (reqSessionId == session::sessionZero)
190 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700191 reqSessionId = session::Manager::get().getSessionIDbyHandle(
192 reqSessionHandle & session::multiIntfaceSessionHandleMask);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000193 if (!reqSessionId)
194 {
195 return session::ccInvalidSessionHandle;
196 }
197 }
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000198 }
199 catch (const std::exception& e)
200 {
201 log<level::ERR>("Failed to get session manager instance or sessionID "
202 "by sessionHandle",
203 entry("ERRMSG=%s", e.what()));
204 return session::ccInvalidSessionHandle;
205 }
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000206
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000207 try
208 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000209 auto closeSessionInstance =
Vernon Mauery2085ae02021-06-10 11:51:00 -0700210 session::Manager::get().getSession(reqSessionId);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000211 uint8_t closeSessionPriv = closeSessionInstance->currentPrivilege();
212
213 if (currentSessionPriv < closeSessionPriv)
214 {
215 return ipmi::ccInsufficientPrivilege;
216 }
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000217 }
218 catch (const std::exception& e)
219 {
220 log<level::ERR>("Failed to get session manager instance or sessionID",
221 entry("ERRMSG=%s", e.what()));
222 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 {
Jayaprakash Mutyalaaf23add2021-11-18 22:29:38 +0000236 log<level::ERR>(
237 "Failed to get session manager instance or stop session",
238 entry("ERRMSG=%s", e.what()));
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 Williams12d199b2021-10-06 12:36:48 -0500300 catch (const sdbusplus::exception::exception& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000301 {
302 log<level::ERR>("Failed to fetch object from dbus",
303 entry("INTERFACE=%s", session::sessionIntf),
304 entry("ERRMSG=%s", e.what()));
305 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