blob: aa20941ec1570d592224d64aa007a347fdf84177 [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 }
30
31 std::vector<uint8_t> outPayload(sizeof(SetSessionPrivLevelResp));
Vernon Mauery9e801a22018-10-12 13:20:49 -070032 auto response =
33 reinterpret_cast<SetSessionPrivLevelResp*>(outPayload.data());
Tom Joseph9662c3a2016-12-06 17:52:16 +053034 response->completionCode = IPMI_CC_OK;
35 uint8_t reqPrivilegeLevel = request->reqPrivLevel;
36
Vernon Mauery41ff9b52021-06-11 11:37:40 -070037 auto session = session::Manager::get().getSession(handler->sessionID);
Tom Joseph9662c3a2016-12-06 17:52:16 +053038
39 if (reqPrivilegeLevel == 0) // Just return present privilege level
40 {
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053041 response->newPrivLevel = session->currentPrivilege();
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053042 return outPayload;
Tom Joseph9662c3a2016-12-06 17:52:16 +053043 }
Tom Joseph4021b1f2019-02-12 10:10:12 +053044 if (reqPrivilegeLevel > (static_cast<uint8_t>(session->reqMaxPrivLevel) &
45 session::reqMaxPrivMask))
Tom Joseph9662c3a2016-12-06 17:52:16 +053046 {
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053047 // Requested level exceeds Channel and/or User Privilege Limit
48 response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
49 return outPayload;
50 }
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053051 // Use the minimum privilege of user or channel
52 uint8_t minPriv = 0;
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053053 if (session->sessionChannelAccess.privLimit <
54 session->sessionUserPrivAccess.privilege)
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053055 {
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053056 minPriv = session->sessionChannelAccess.privLimit;
Tom Joseph9662c3a2016-12-06 17:52:16 +053057 }
58 else
59 {
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053060 minPriv = session->sessionUserPrivAccess.privilege;
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053061 }
62 if (reqPrivilegeLevel > minPriv)
63 {
Tom Joseph9662c3a2016-12-06 17:52:16 +053064 // Requested level exceeds Channel and/or User Privilege Limit
65 response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
66 }
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053067 else
68 {
69 // update current privilege of the session.
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053070 session->currentPrivilege(static_cast<uint8_t>(reqPrivilegeLevel));
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053071 response->newPrivLevel = reqPrivilegeLevel;
72 }
73
Tom Joseph9662c3a2016-12-06 17:52:16 +053074 return outPayload;
75}
76
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +000077/**
78 * @brief set the session state as teardown
79 *
80 * This function is to set the session state to tear down in progress if the
81 * state is active.
82 *
83 * @param[in] busp - Dbus obj
84 * @param[in] service - service name
85 * @param[in] obj - object path
86 *
87 * @return success completion code if it sets the session state to
88 * tearDownInProgress else return the corresponding error completion code.
89 **/
90uint8_t setSessionState(std::shared_ptr<sdbusplus::asio::connection>& busp,
91 const std::string& service, const std::string& obj)
92{
93 try
94 {
95 uint8_t sessionState = std::get<uint8_t>(ipmi::getDbusProperty(
96 *busp, service, obj, session::sessionIntf, "State"));
97
98 if (sessionState == static_cast<uint8_t>(session::State::active))
99 {
100 ipmi::setDbusProperty(
101 *busp, service, obj, session::sessionIntf, "State",
102 static_cast<uint8_t>(session::State::tearDownInProgress));
103 return ipmi::ccSuccess;
104 }
105 }
106 catch (std::exception& e)
107 {
108 log<level::ERR>("Failed in getting session state property",
109 entry("service=%s", service.c_str()),
110 entry("object path=%s", obj.c_str()),
111 entry("interface=%s", session::sessionIntf));
112 return ipmi::ccUnspecifiedError;
113 }
114
115 return ipmi::ccInvalidFieldRequest;
116}
117
118uint8_t closeOtherNetInstanceSession(const uint32_t reqSessionId,
119 const uint8_t reqSessionHandle,
120 const uint8_t currentSessionPriv)
121{
122 auto busp = getSdBus();
123
124 try
125 {
126 ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
127 *busp, session::sessionManagerRootPath, session::sessionIntf);
128
129 for (auto& objectTreeItr : objectTree)
130 {
131 const std::string obj = objectTreeItr.first;
132
133 if (isSessionObjectMatched(obj, reqSessionId, reqSessionHandle))
134 {
135 auto& serviceMap = objectTreeItr.second;
136
137 if (serviceMap.size() != 1)
138 {
139 return ipmi::ccUnspecifiedError;
140 }
141
142 auto itr = serviceMap.begin();
143 const std::string service = itr->first;
144 uint8_t closeSessionPriv =
145 std::get<uint8_t>(ipmi::getDbusProperty(
146 *busp, service, obj, session::sessionIntf,
147 "CurrentPrivilege"));
148
149 if (currentSessionPriv < closeSessionPriv)
150 {
151 return ipmi::ccInsufficientPrivilege;
152 }
153 return setSessionState(busp, service, obj);
154 }
155 }
156 }
Patrick Williams1c5b3ab2021-09-02 09:45:12 -0500157 catch (sdbusplus::exception::exception& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000158 {
159 log<level::ERR>("Failed to fetch object from dbus",
160 entry("INTERFACE=%s", session::sessionIntf),
161 entry("ERRMSG=%s", e.what()));
162 return ipmi::ccUnspecifiedError;
163 }
164
165 return ipmi::ccInvalidFieldRequest;
166}
167
168uint8_t closeMyNetInstanceSession(uint32_t reqSessionId,
169 uint8_t reqSessionHandle,
170 const uint8_t currentSessionPriv)
171{
172 bool status = false;
173
174 try
175 {
176 if (reqSessionId == session::sessionZero)
177 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700178 reqSessionId = session::Manager::get().getSessionIDbyHandle(
179 reqSessionHandle & session::multiIntfaceSessionHandleMask);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000180 if (!reqSessionId)
181 {
182 return session::ccInvalidSessionHandle;
183 }
184 }
185
186 auto closeSessionInstance =
Vernon Mauery2085ae02021-06-10 11:51:00 -0700187 session::Manager::get().getSession(reqSessionId);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000188 uint8_t closeSessionPriv = closeSessionInstance->currentPrivilege();
189
190 if (currentSessionPriv < closeSessionPriv)
191 {
192 return ipmi::ccInsufficientPrivilege;
193 }
Vernon Mauery2085ae02021-06-10 11:51:00 -0700194 status = session::Manager::get().stopSession(reqSessionId);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000195
196 if (!status)
197 {
198 return session::ccInvalidSessionId;
199 }
200 }
201 catch (std::exception& e)
202 {
203 log<level::ERR>("Failed to get session manager instance",
204 entry("ERRMSG=%s", e.what()));
205 return ipmi::ccUnspecifiedError;
206 }
207
208 return ipmi::ccSuccess;
209}
210
Tom Joseph18a45e92017-04-11 11:30:44 +0530211std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
Vernon Mauery41ff9b52021-06-11 11:37:40 -0700212 std::shared_ptr<message::Handler>& handler)
Tom Joseph9662c3a2016-12-06 17:52:16 +0530213{
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700214 // minimum inPayload size is reqSessionId (uint32_t)
215 // maximum inPayload size is struct CloseSessionRequest
216 if (inPayload.size() != sizeof(uint32_t) &&
217 inPayload.size() != sizeof(CloseSessionRequest))
218 {
219 std::vector<uint8_t> errorPayload{IPMI_CC_REQ_DATA_LEN_INVALID};
220 return errorPayload;
221 }
222
Vernon Mauery9e801a22018-10-12 13:20:49 -0700223 auto request =
224 reinterpret_cast<const CloseSessionRequest*>(inPayload.data());
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700225
226 std::vector<uint8_t> outPayload(sizeof(CloseSessionResponse));
Tom Joseph9662c3a2016-12-06 17:52:16 +0530227 auto response = reinterpret_cast<CloseSessionResponse*>(outPayload.data());
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000228 uint32_t reqSessionId = request->sessionID;
229 uint8_t ipmiNetworkInstance = 0;
230 uint8_t currentSessionPriv = 0;
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700231 uint8_t reqSessionHandle = session::invalidSessionHandle;
232
233 if (inPayload.size() == sizeof(CloseSessionRequest))
234 {
235 reqSessionHandle = request->sessionHandle;
236 }
Tom Joseph9662c3a2016-12-06 17:52:16 +0530237
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000238 if (reqSessionId == session::sessionZero &&
239 reqSessionHandle == session::invalidSessionHandle)
Tom Joseph9662c3a2016-12-06 17:52:16 +0530240 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000241 response->completionCode = session::ccInvalidSessionHandle;
242 return outPayload;
243 }
244
245 if (inPayload.size() == sizeof(reqSessionId) &&
246 reqSessionId == session::sessionZero)
247 {
248 response->completionCode = session::ccInvalidSessionId;
249 return outPayload;
250 }
251
252 if (reqSessionId != session::sessionZero &&
253 inPayload.size() != sizeof(reqSessionId))
254 {
255 response->completionCode = ipmi::ccInvalidFieldRequest;
256 return outPayload;
257 }
258
259 try
260 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700261 ipmiNetworkInstance = session::Manager::get().getNetworkInstance();
262 auto currentSession =
Vernon Mauery41ff9b52021-06-11 11:37:40 -0700263 session::Manager::get().getSession(handler->sessionID);
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000264 currentSessionPriv = currentSession->currentPrivilege();
265 }
Patrick Williams1c5b3ab2021-09-02 09:45:12 -0500266 catch (sdbusplus::exception::exception& e)
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000267 {
268 log<level::ERR>("Failed to fetch object from dbus",
269 entry("INTERFACE=%s", session::sessionIntf),
270 entry("ERRMSG=%s", e.what()));
271 response->completionCode = ipmi::ccUnspecifiedError;
272 return outPayload;
273 }
274
275 if (reqSessionId >> myNetInstanceSessionIdShiftMask ==
276 ipmiNetworkInstance ||
277 (reqSessionId == session::sessionZero &&
278 (reqSessionHandle >> myNetInstanceSessionHandleShiftMask ==
279 ipmiNetworkInstance)))
280 {
281 response->completionCode = closeMyNetInstanceSession(
282 reqSessionId, reqSessionHandle, currentSessionPriv);
Vernon Mauery2085ae02021-06-10 11:51:00 -0700283 session::Manager::get().scheduleSessionCleaner(100us);
Tom Joseph9662c3a2016-12-06 17:52:16 +0530284 }
285 else
286 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000287 response->completionCode = closeOtherNetInstanceSession(
288 reqSessionId, reqSessionHandle, currentSessionPriv);
Tom Joseph9662c3a2016-12-06 17:52:16 +0530289 }
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000290
Tom Joseph9662c3a2016-12-06 17:52:16 +0530291 return outPayload;
292}
293
294} // namespace command