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