Enforce encryption/authentication on in-session RMCP+ messages

In-session RMCP+ messages must have the encryption set to match the
negotiated encryption setting that was set at session creation time.

Tested: Attempt to send an unencrypted payload with a valid session ID.

Change-Id: Iaa20cb9df9b2224bb81e3be5808cab9202e6dbf4
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/message_parsers.cpp b/message_parsers.cpp
index f916171..b3d8dbd 100644
--- a/message_parsers.cpp
+++ b/message_parsers.cpp
@@ -171,12 +171,21 @@
         throw std::runtime_error("IPMI2.0 Session Header Missing");
     }
 
-    auto message = std::make_shared<Message>();
-
     auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
 
+    uint32_t sessionID = endian::from_ipmi(header->sessId);
+
+    auto session =
+        std::get<session::Manager&>(singletonPool).getSession(sessionID);
+    if (!session)
+    {
+        throw std::runtime_error("RMCP+ message from unknown session");
+    }
+
+    auto message = std::make_shared<Message>();
+
     message->payloadType = static_cast<PayloadType>(header->payloadType & 0x3F);
-    message->bmcSessionID = endian::from_ipmi(header->sessId);
+    message->bmcSessionID = sessionID;
     message->sessionSeqNum = endian::from_ipmi(header->sessSeqNum);
     message->isPacketEncrypted =
         ((header->payloadType & PAYLOAD_ENCRYPT_MASK) ? true : false);
@@ -193,6 +202,17 @@
         throw std::runtime_error("Invalid data length");
     }
 
+    bool integrityMismatch =
+        session->isIntegrityAlgoEnabled() && !message->isPacketAuthenticated;
+    bool encryptMismatch =
+        session->isCryptAlgoEnabled() && !message->isPacketEncrypted;
+
+    if (sessionID != session::sessionZero &&
+        (integrityMismatch || encryptMismatch))
+    {
+        throw std::runtime_error("unencrypted or unauthenticated message");
+    }
+
     if (message->isPacketAuthenticated)
     {
         if (!(internal::verifyPacketIntegrity(inPacket, message, payloadLen)))