Add privilege check in activate payload
When a user's privilege is lower than sol privilege level, payload
activate and deactivate command will be executed failed with this user.
Refer to ipmi spec v2.0 Appendix G, The configuration parameters for a
given payload type determine the privilege level required to activate
and deactivate the payload.
Tested:
1. Check sol privilege level
```
~# ipmitool -I lanplus -H $ip -U $username -P $password sol activate
[SOL Session operational. Use ~? for help]
SOL session closed by BMC
```
~# ipmitool -I lanplus -H $ip -U $username -P $password sol info
```
Info: SOL parameter 'Nonvolatile Bitrate (5)' not supported
Info: SOL parameter 'Volatile Bitrate (6)' not supported
Set in progress : set-complete
Enabled : true
Force Encryption : false
Force Authentication : false
Privilege Level : ADMINISTRATOR
Character Accumulate Level (ms) : 60
Character Send Threshold : 96
Retry Count : 7
Retry Interval (ms) : 500
Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting
Non-Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting
Payload Channel : 1 (0x01)
Payload Port : 623
```
2. Set the privilege of user to 'Operator', run 'sol activate'
and 'sol deactivate'
```
~# ipmitool -I lanplus -H $ip -U $username -P $password sol activate -L OPERATOR
Error activating SOL payload: Insufficient privilege level
~# ipmitool -I lanplus -H $ip -U $username -P $password sol deactivate -L OPERATOR
Error de-activating SOL payload: Insufficient privilege level
```
3. Set the privilege of user to 'ReadOnly', run 'sol activate'
and 'sol deactivate'
```
~# ipmitool -I lanplus -H $ip -U $username -P $password sol activate -L USER
Error activating SOL payload: Insufficient privilege level
~# ipmitool -I lanplus -H $ip -U $username -P $password sol deactivate -L USER
Error de-activating SOL payload: Insufficient privilege level
```
4. Create new users test1 and test2 with 'ReadOnly' privilege,
set sol privilege to 'ReadOnly', run 'sol activate' with test1
```
~# ipmitool -I lanplus -H $ip -U $username -P $password sol set privilege-level user
~# ipmitool -I lanplus -H $ip -U test1 -P $password sol activate -L USER
[SOL Session operational. Use ~? for help]
```
On another console, deactivate session owned by test1
```
~# ipmitool -I lanplus -H $ip -U test2 -P $password sol deactivate -L USER
Error de-activating SOL payload: Insufficient privilege level
~# ipmitool -I lanplus -H $ip -U test1 -P $password sol deactivate -L USER
```
Session owned by test1 cannot be deactivated by test2, can be
deactivated by test1
Signed-off-by: Tang Yiwei <tangyiwei.2022@bytedance.com>
Change-Id: Ie5ca60c9891140614b701392c94245e916cd97ab
diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
index b3bcca2..e38473c 100644
--- a/command/payload_cmds.cpp
+++ b/command/payload_cmds.cpp
@@ -62,6 +62,13 @@
return outPayload;
}
+ if (session->currentPrivilege() <
+ static_cast<uint8_t>(sol::Manager::get().solMinPrivilege))
+ {
+ response->completionCode = IPMI_CC_INSUFFICIENT_PRIVILEGE;
+ return outPayload;
+ }
+
// Is SOL Payload enabled for this user & channel.
auto userId = ipmi::ipmiUserGetUserId(session->userName);
ipmi::PayloadAccess payloadAccess = {};
@@ -109,7 +116,7 @@
std::vector<uint8_t>
deactivatePayload(const std::vector<uint8_t>& inPayload,
- std::shared_ptr<message::Handler>& /* handler */)
+ std::shared_ptr<message::Handler>& handler)
{
auto request =
reinterpret_cast<const DeactivatePayloadRequest*>(inPayload.data());
@@ -145,17 +152,27 @@
return outPayload;
}
+ auto currentSession =
+ session::Manager::get().getSession(handler->sessionID);
+ auto solSessionID =
+ sol::Manager::get().getContext(request->payloadInstance).sessionID;
+ auto solActiveSession = session::Manager::get().getSession(solSessionID);
+ // The session owner or the ADMIN could deactivate the session
+ if (currentSession->userName != solActiveSession->userName &&
+ currentSession->currentPrivilege() !=
+ static_cast<uint8_t>(session::Privilege::ADMIN))
+ {
+ response->completionCode = IPMI_CC_INSUFFICIENT_PRIVILEGE;
+ return outPayload;
+ }
+
try
{
- auto& context =
- sol::Manager::get().getContext(request->payloadInstance);
- auto sessionID = context.sessionID;
-
sol::Manager::get().stopPayloadInstance(request->payloadInstance);
try
{
- activating(request->payloadInstance, sessionID);
+ activating(request->payloadInstance, solSessionID);
}
catch (const std::exception& e)
{
@@ -164,7 +181,7 @@
/*
* In case session has been closed (like in the case of inactivity
* timeout), then activating function would throw an exception,
- * since sessionID is not found. IPMI success completion code is
+ * since solSessionID is not found. IPMI success completion code is
* returned, since the session is closed.
*/
return outPayload;