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