blob: a08e8f2a576ca58946c717f219d7f1689a900770 [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"
4#include "main.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
Tom Joseph9662c3a2016-12-06 17:52:16 +053012namespace command
13{
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +000014using namespace phosphor::logging;
Tom Joseph9662c3a2016-12-06 17:52:16 +053015
Vernon Mauery9e801a22018-10-12 13:20:49 -070016std::vector<uint8_t>
17 setSessionPrivilegeLevel(const std::vector<uint8_t>& inPayload,
18 const message::Handler& handler)
Tom Joseph9662c3a2016-12-06 17:52:16 +053019{
Tom Joseph9662c3a2016-12-06 17:52:16 +053020
21 std::vector<uint8_t> outPayload(sizeof(SetSessionPrivLevelResp));
Vernon Mauery9e801a22018-10-12 13:20:49 -070022 auto request =
23 reinterpret_cast<const SetSessionPrivLevelReq*>(inPayload.data());
24 auto response =
25 reinterpret_cast<SetSessionPrivLevelResp*>(outPayload.data());
Tom Joseph9662c3a2016-12-06 17:52:16 +053026 response->completionCode = IPMI_CC_OK;
27 uint8_t reqPrivilegeLevel = request->reqPrivLevel;
28
Vernon Maueryae1fda42018-10-15 12:55:34 -070029 auto session = std::get<session::Manager&>(singletonPool)
30 .getSession(handler.sessionID);
Tom Joseph9662c3a2016-12-06 17:52:16 +053031
32 if (reqPrivilegeLevel == 0) // Just return present privilege level
33 {
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053034 response->newPrivLevel = session->currentPrivilege();
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053035 return outPayload;
Tom Joseph9662c3a2016-12-06 17:52:16 +053036 }
Tom Joseph4021b1f2019-02-12 10:10:12 +053037 if (reqPrivilegeLevel > (static_cast<uint8_t>(session->reqMaxPrivLevel) &
38 session::reqMaxPrivMask))
Tom Joseph9662c3a2016-12-06 17:52:16 +053039 {
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053040 // Requested level exceeds Channel and/or User Privilege Limit
41 response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
42 return outPayload;
43 }
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053044 // Use the minimum privilege of user or channel
45 uint8_t minPriv = 0;
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053046 if (session->sessionChannelAccess.privLimit <
47 session->sessionUserPrivAccess.privilege)
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053048 {
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053049 minPriv = session->sessionChannelAccess.privLimit;
Tom Joseph9662c3a2016-12-06 17:52:16 +053050 }
51 else
52 {
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053053 minPriv = session->sessionUserPrivAccess.privilege;
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053054 }
55 if (reqPrivilegeLevel > minPriv)
56 {
Tom Joseph9662c3a2016-12-06 17:52:16 +053057 // Requested level exceeds Channel and/or User Privilege Limit
58 response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
59 }
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053060 else
61 {
62 // update current privilege of the session.
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053063 session->currentPrivilege(static_cast<uint8_t>(reqPrivilegeLevel));
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053064 response->newPrivLevel = reqPrivilegeLevel;
65 }
66
Tom Joseph9662c3a2016-12-06 17:52:16 +053067 return outPayload;
68}
69
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +000070/**
71 * @brief set the session state as teardown
72 *
73 * This function is to set the session state to tear down in progress if the
74 * state is active.
75 *
76 * @param[in] busp - Dbus obj
77 * @param[in] service - service name
78 * @param[in] obj - object path
79 *
80 * @return success completion code if it sets the session state to
81 * tearDownInProgress else return the corresponding error completion code.
82 **/
83uint8_t setSessionState(std::shared_ptr<sdbusplus::asio::connection>& busp,
84 const std::string& service, const std::string& obj)
85{
86 try
87 {
88 uint8_t sessionState = std::get<uint8_t>(ipmi::getDbusProperty(
89 *busp, service, obj, session::sessionIntf, "State"));
90
91 if (sessionState == static_cast<uint8_t>(session::State::active))
92 {
93 ipmi::setDbusProperty(
94 *busp, service, obj, session::sessionIntf, "State",
95 static_cast<uint8_t>(session::State::tearDownInProgress));
96 return ipmi::ccSuccess;
97 }
98 }
99 catch (std::exception& e)
100 {
101 log<level::ERR>("Failed in getting session state property",
102 entry("service=%s", service.c_str()),
103 entry("object path=%s", obj.c_str()),
104 entry("interface=%s", session::sessionIntf));
105 return ipmi::ccUnspecifiedError;
106 }
107
108 return ipmi::ccInvalidFieldRequest;
109}
110
111uint8_t closeOtherNetInstanceSession(const uint32_t reqSessionId,
112 const uint8_t reqSessionHandle,
113 const uint8_t currentSessionPriv)
114{
115 auto busp = getSdBus();
116
117 try
118 {
119 ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
120 *busp, session::sessionManagerRootPath, session::sessionIntf);
121
122 for (auto& objectTreeItr : objectTree)
123 {
124 const std::string obj = objectTreeItr.first;
125
126 if (isSessionObjectMatched(obj, reqSessionId, reqSessionHandle))
127 {
128 auto& serviceMap = objectTreeItr.second;
129
130 if (serviceMap.size() != 1)
131 {
132 return ipmi::ccUnspecifiedError;
133 }
134
135 auto itr = serviceMap.begin();
136 const std::string service = itr->first;
137 uint8_t closeSessionPriv =
138 std::get<uint8_t>(ipmi::getDbusProperty(
139 *busp, service, obj, session::sessionIntf,
140 "CurrentPrivilege"));
141
142 if (currentSessionPriv < closeSessionPriv)
143 {
144 return ipmi::ccInsufficientPrivilege;
145 }
146 return setSessionState(busp, service, obj);
147 }
148 }
149 }
150 catch (sdbusplus::exception::SdBusError& e)
151 {
152 log<level::ERR>("Failed to fetch object from dbus",
153 entry("INTERFACE=%s", session::sessionIntf),
154 entry("ERRMSG=%s", e.what()));
155 return ipmi::ccUnspecifiedError;
156 }
157
158 return ipmi::ccInvalidFieldRequest;
159}
160
161uint8_t closeMyNetInstanceSession(uint32_t reqSessionId,
162 uint8_t reqSessionHandle,
163 const uint8_t currentSessionPriv)
164{
165 bool status = false;
166
167 try
168 {
169 if (reqSessionId == session::sessionZero)
170 {
171 reqSessionId = std::get<session::Manager&>(singletonPool)
172 .getSessionIDbyHandle(
173 reqSessionHandle &
174 session::multiIntfaceSessionHandleMask);
175 if (!reqSessionId)
176 {
177 return session::ccInvalidSessionHandle;
178 }
179 }
180
181 auto closeSessionInstance =
182 std::get<session::Manager&>(singletonPool).getSession(reqSessionId);
183 uint8_t closeSessionPriv = closeSessionInstance->currentPrivilege();
184
185 if (currentSessionPriv < closeSessionPriv)
186 {
187 return ipmi::ccInsufficientPrivilege;
188 }
189 status = std::get<session::Manager&>(singletonPool)
190 .stopSession(reqSessionId);
191
192 if (!status)
193 {
194 return session::ccInvalidSessionId;
195 }
196 }
197 catch (std::exception& e)
198 {
199 log<level::ERR>("Failed to get session manager instance",
200 entry("ERRMSG=%s", e.what()));
201 return ipmi::ccUnspecifiedError;
202 }
203
204 return ipmi::ccSuccess;
205}
206
Tom Joseph18a45e92017-04-11 11:30:44 +0530207std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
Tom Joseph9662c3a2016-12-06 17:52:16 +0530208 const message::Handler& handler)
209{
Tom Joseph9662c3a2016-12-06 17:52:16 +0530210 std::vector<uint8_t> outPayload(sizeof(CloseSessionResponse));
Vernon Mauery9e801a22018-10-12 13:20:49 -0700211 auto request =
212 reinterpret_cast<const CloseSessionRequest*>(inPayload.data());
Tom Joseph9662c3a2016-12-06 17:52:16 +0530213 auto response = reinterpret_cast<CloseSessionResponse*>(outPayload.data());
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000214 uint32_t reqSessionId = request->sessionID;
215 uint8_t ipmiNetworkInstance = 0;
216 uint8_t currentSessionPriv = 0;
217 uint8_t reqSessionHandle = request->sessionHandle;
Tom Joseph9662c3a2016-12-06 17:52:16 +0530218
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000219 if (reqSessionId == session::sessionZero &&
220 reqSessionHandle == session::invalidSessionHandle)
Tom Joseph9662c3a2016-12-06 17:52:16 +0530221 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000222 response->completionCode = session::ccInvalidSessionHandle;
223 return outPayload;
224 }
225
226 if (inPayload.size() == sizeof(reqSessionId) &&
227 reqSessionId == session::sessionZero)
228 {
229 response->completionCode = session::ccInvalidSessionId;
230 return outPayload;
231 }
232
233 if (reqSessionId != session::sessionZero &&
234 inPayload.size() != sizeof(reqSessionId))
235 {
236 response->completionCode = ipmi::ccInvalidFieldRequest;
237 return outPayload;
238 }
239
240 try
241 {
242 ipmiNetworkInstance =
243 std::get<session::Manager&>(singletonPool).getNetworkInstance();
244 auto currentSession = std::get<session::Manager&>(singletonPool)
245 .getSession(handler.sessionID);
246 currentSessionPriv = currentSession->currentPrivilege();
247 }
248 catch (sdbusplus::exception::SdBusError& e)
249 {
250 log<level::ERR>("Failed to fetch object from dbus",
251 entry("INTERFACE=%s", session::sessionIntf),
252 entry("ERRMSG=%s", e.what()));
253 response->completionCode = ipmi::ccUnspecifiedError;
254 return outPayload;
255 }
256
257 if (reqSessionId >> myNetInstanceSessionIdShiftMask ==
258 ipmiNetworkInstance ||
259 (reqSessionId == session::sessionZero &&
260 (reqSessionHandle >> myNetInstanceSessionHandleShiftMask ==
261 ipmiNetworkInstance)))
262 {
263 response->completionCode = closeMyNetInstanceSession(
264 reqSessionId, reqSessionHandle, currentSessionPriv);
Tom Joseph9662c3a2016-12-06 17:52:16 +0530265 }
266 else
267 {
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000268 response->completionCode = closeOtherNetInstanceSession(
269 reqSessionId, reqSessionHandle, currentSessionPriv);
Tom Joseph9662c3a2016-12-06 17:52:16 +0530270 }
Rajashekar Gade Reddydafe3642019-07-12 17:35:06 +0000271
Tom Joseph9662c3a2016-12-06 17:52:16 +0530272 return outPayload;
273}
274
275} // namespace command