Restrict ME bridging commands

Restrict sensitive ME commands sent via BMC bridging
commands, and return invalid field in request as response
for those.

Tested:
Verified response invalid field in request for the following
ipmitool -t 0x2C -b 0x1 raw 0x6 0x52 0x57 0x0 0x20 0x1 0x0
and got proper response for
ipmitool -t 0x2C -b 0x1 raw 6 1

Change-Id: I53fae25ae27e7d1c257871d2cbadfea6f4c4ba17
Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
diff --git a/src/bridgingcommands.cpp b/src/bridgingcommands.cpp
index 88d29b4..b4f0264 100644
--- a/src/bridgingcommands.cpp
+++ b/src/bridgingcommands.cpp
@@ -186,6 +186,48 @@
     mesg.append(ipmbMeChannelNum, netFn, rqLun, cmd, data);
 }
 
+static constexpr unsigned int makeCmdKey(unsigned int netFn, unsigned int cmd)
+{
+    return (netFn << 8) | cmd;
+}
+
+static constexpr bool isMeCmdAllowed(uint8_t netFn, uint8_t cmd)
+{
+    constexpr uint8_t netFnMeOEM = 0x2E;
+    constexpr uint8_t cmdMeOemSendRawPeci = 0x40;
+    constexpr uint8_t cmdMeOemAggSendRawPeci = 0x41;
+    constexpr uint8_t cmdMeOemCpuPkgConfWrite = 0x43;
+    constexpr uint8_t cmdMeOemCpuPciConfWrite = 0x45;
+    constexpr uint8_t cmdMeOemReadMemSmbus = 0x47;
+    constexpr uint8_t cmdMeOemWriteMemSmbus = 0x48;
+    constexpr uint8_t cmdMeOemSlotIpmb = 0x51;
+    constexpr uint8_t cmdMeOemSlotI2cMasterWriteRead = 0x52;
+    constexpr uint8_t cmdMeOemSendRawPmbus = 0xD9;
+    constexpr uint8_t cmdMeOemUnlockMeRegion = 0xE7;
+    constexpr uint8_t cmdMeOemAggSendRawPmbus = 0xEC;
+
+    switch (makeCmdKey(netFn, cmd))
+    {
+        // Restrict ME Master write command
+        case makeCmdKey(ipmi::netFnApp, ipmi::app::cmdMasterWriteRead):
+        // Restrict ME OEM commands
+        case makeCmdKey(netFnMeOEM, cmdMeOemSendRawPeci):
+        case makeCmdKey(netFnMeOEM, cmdMeOemAggSendRawPeci):
+        case makeCmdKey(netFnMeOEM, cmdMeOemCpuPkgConfWrite):
+        case makeCmdKey(netFnMeOEM, cmdMeOemCpuPciConfWrite):
+        case makeCmdKey(netFnMeOEM, cmdMeOemReadMemSmbus):
+        case makeCmdKey(netFnMeOEM, cmdMeOemWriteMemSmbus):
+        case makeCmdKey(netFnMeOEM, cmdMeOemSlotIpmb):
+        case makeCmdKey(netFnMeOEM, cmdMeOemSlotI2cMasterWriteRead):
+        case makeCmdKey(netFnMeOEM, cmdMeOemSendRawPmbus):
+        case makeCmdKey(netFnMeOEM, cmdMeOemUnlockMeRegion):
+        case makeCmdKey(netFnMeOEM, cmdMeOemAggSendRawPmbus):
+            return false;
+        default:
+            return true;
+    }
+}
+
 ipmi_return_codes Bridging::handleIpmbChannel(sSendMessageReq *sendMsgReq,
                                               ipmi_response_t response,
                                               ipmi_data_len_t dataLen)
@@ -210,6 +252,13 @@
         return IPMI_CC_PARM_OUT_OF_RANGE;
     }
 
+    constexpr uint8_t shiftLUN = 2;
+    if (!isMeCmdAllowed((sendMsgReqData->Header.Req.rsNetFnLUN >> shiftLUN),
+                        sendMsgReqData->Header.Req.cmd))
+    {
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+
     // check allowed modes
     if (sendMsgReq->modeGet() != modeNoTracking &&
         sendMsgReq->modeGet() != modeTrackRequest)