Log Redfish event for invalid login via RMCPP interface

This commit adds support for logging RedFish event log while user tries
to attempt login with invalid credentials.
When user trying to login with invalid credentials on RMCP+ session
interface event should be logged in RedFish event log.
This is a requirement for system events auditing purpose.

Tested:
1. Login with wrong credentials on RMCP+ interface.
2. Verified RedFish event logged successfully.

"Members": [
        {
            "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/1622785246",
            "@odata.type": "#LogEntry.v1_4_0.LogEntry",
            "Created": "2021-06-04T05:40:46+00:00",
            "EntryType": "Event",
            "Id": "1622785246",
            "Message": "Invalid username or password attempted on RMCPP.",
            "MessageArgs": [
                "RMCP+"
            ],
            "MessageId": "OpenBMC.0.1.InvalidLoginAttempted",
            "Name": "System Event Log Entry",
            "Severity": "Warning"
        }
    ],
    "Members@odata.count": 1,
    "Name": "System Event Log Entries"
}

3. Verified RedFish validator passed

Signed-off-by: sunitakx <sunitax.kumari@linux.intel.com>
Change-Id: I40b37ff5dd518c52d01b00196e8607c9762a17bf
diff --git a/command/rakp12.cpp b/command/rakp12.cpp
index 912a1d0..cd84889 100644
--- a/command/rakp12.cpp
+++ b/command/rakp12.cpp
@@ -23,6 +23,19 @@
            static_cast<uint8_t>(ipmi::EChannelAccessMode::disabled);
 }
 
+void logInvalidLoginRedfishEvent(const std::string& journalMsg,
+                                 const std::optional<std::string>& messageArgs)
+{
+    static constexpr std::string_view openBMCMessageRegistryVersion = "0.1.";
+    std::string messageID = "OpenBMC." +
+                            std::string(openBMCMessageRegistryVersion) +
+                            "InvalidLoginAttempted";
+    phosphor::logging::log<phosphor::logging::level::ERR>(
+        journalMsg.c_str(),
+        phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageID.c_str()),
+        phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
+                                 messageArgs.value().c_str()));
+}
 std::vector<uint8_t> RAKP12(const std::vector<uint8_t>& inPayload,
                             std::shared_ptr<message::Handler>& handler)
 {
@@ -65,12 +78,14 @@
     auto rakp1Size =
         sizeof(RAKP1request) - (userNameMaxLen - request->user_name_len);
 
+    std::string message = "Invalid login attempted via RCMPP interface ";
     // Validate user name length in the message
     if (request->user_name_len > userNameMaxLen ||
         inPayload.size() != rakp1Size)
     {
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::INVALID_NAME_LENGTH);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
 
@@ -157,17 +172,21 @@
         // Yes, NULL user name is not supported for security reasons.
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
 
     // Perform user name based lookup
     std::string userName(request->user_name, request->user_name_len);
     std::string passwd;
+
+    message += "user: " + userName;
     uint8_t userId = ipmi::ipmiUserGetUserId(userName);
     if (userId == ipmi::invalidUserId)
     {
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
     // check user is enabled before proceeding.
@@ -177,6 +196,7 @@
     {
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
     // Get the user password for RAKP message authenticate
@@ -185,6 +205,7 @@
     {
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
     // Check whether user is already locked for failed attempts
@@ -195,6 +216,7 @@
 
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
 
@@ -207,6 +229,7 @@
     {
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
     if (!isChannelAccessModeEnabled(session->sessionChannelAccess.accessMode))
@@ -215,6 +238,7 @@
             "Channel access mode disabled.");
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
     if (session->sessionUserPrivAccess.privilege >
@@ -222,6 +246,7 @@
     {
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
     session->channelNum(chNum);
@@ -253,6 +278,8 @@
             "Username/Privilege lookup failed for requested privilege");
         response->rmcpStatusCode =
             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
+
+        logInvalidLoginRedfishEvent(message);
         return outPayload;
     }
 
diff --git a/command/rakp12.hpp b/command/rakp12.hpp
index bf6d4c5..e2eebc2 100644
--- a/command/rakp12.hpp
+++ b/command/rakp12.hpp
@@ -74,5 +74,14 @@
  */
 std::vector<uint8_t> RAKP12(const std::vector<uint8_t>& inPayload,
                             std::shared_ptr<message::Handler>& handler);
-
+/**
+ *@brief Log Redfish event for invalid login attempted on RMCPP interface
+ *
+ * @param[in] journalMsg - Show journal Debug Message in journal logs
+ * @param[in] redfishMsg - Log Redfish Event Message
+ *
+ */
+void logInvalidLoginRedfishEvent(
+    const std::string& journalMsg,
+    const std::optional<std::string>& messageArgs = "RMCPP");
 } // namespace command