1 #include "session_cmds.hpp"
2 
3 #include "endian.hpp"
4 #include "main.hpp"
5 
6 #include <ipmid/api.h>
7 
8 namespace command
9 {
10 
11 std::vector<uint8_t>
12     setSessionPrivilegeLevel(const std::vector<uint8_t>& inPayload,
13                              const message::Handler& handler)
14 {
15 
16     std::vector<uint8_t> outPayload(sizeof(SetSessionPrivLevelResp));
17     auto request =
18         reinterpret_cast<const SetSessionPrivLevelReq*>(inPayload.data());
19     auto response =
20         reinterpret_cast<SetSessionPrivLevelResp*>(outPayload.data());
21     response->completionCode = IPMI_CC_OK;
22     uint8_t reqPrivilegeLevel = request->reqPrivLevel;
23 
24     auto session = std::get<session::Manager&>(singletonPool)
25                        .getSession(handler.sessionID);
26 
27     if (reqPrivilegeLevel == 0) // Just return present privilege level
28     {
29         response->newPrivLevel = session->currentPrivilege();
30         return outPayload;
31     }
32     if (reqPrivilegeLevel > (static_cast<uint8_t>(session->reqMaxPrivLevel) &
33                              session::reqMaxPrivMask))
34     {
35         // Requested level exceeds Channel and/or User Privilege Limit
36         response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
37         return outPayload;
38     }
39     // Use the minimum privilege of user or channel
40     uint8_t minPriv = 0;
41     if (session->sessionChannelAccess.privLimit <
42         session->sessionUserPrivAccess.privilege)
43     {
44         minPriv = session->sessionChannelAccess.privLimit;
45     }
46     else
47     {
48         minPriv = session->sessionUserPrivAccess.privilege;
49     }
50     if (reqPrivilegeLevel > minPriv)
51     {
52         // Requested level exceeds Channel and/or User Privilege Limit
53         response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
54     }
55     else
56     {
57         // update current privilege of the session.
58         session->currentPrivilege(static_cast<uint8_t>(reqPrivilegeLevel));
59         response->newPrivLevel = reqPrivilegeLevel;
60     }
61 
62     return outPayload;
63 }
64 
65 std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
66                                   const message::Handler& handler)
67 {
68     std::vector<uint8_t> outPayload(sizeof(CloseSessionResponse));
69     auto request =
70         reinterpret_cast<const CloseSessionRequest*>(inPayload.data());
71     auto response = reinterpret_cast<CloseSessionResponse*>(outPayload.data());
72     response->completionCode = IPMI_CC_OK;
73 
74     auto bmcSessionID = endian::from_ipmi(request->sessionID);
75 
76     // Session 0 is needed to handle session setup, so session zero is never
77     // closed
78     if (bmcSessionID == session::sessionZero)
79     {
80         response->completionCode = IPMI_CC_INVALID_SESSIONID;
81     }
82     else
83     {
84         auto status = std::get<session::Manager&>(singletonPool)
85                           .stopSession(bmcSessionID);
86         if (!status)
87         {
88             response->completionCode = IPMI_CC_INVALID_SESSIONID;
89         }
90     }
91     return outPayload;
92 }
93 
94 } // namespace command
95