Return the maximum privilege in open session command

This commit does the following:

- Set the maximum privilege role in the session instead of current privilege
  in the implementation of the open session request/response.

- In open session response, return the maximum privilege of the session
  instead of the current privilege level.

- Update RAKP12 and RAKP34 implementation

Tested: Checked the session setup works fine with ipmitool and freeipmi
utility ipmipower.

Change-Id: I41b63b91f08c2ed96856c4db41eedaa878c663e3
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/command/open_session.cpp b/command/open_session.cpp
index 51da9e1..e3453f8 100644
--- a/command/open_session.cpp
+++ b/command/open_session.cpp
@@ -38,6 +38,22 @@
         return outPayload;
     }
 
+    session::Privilege priv;
+
+    // 0h in the requested maximum privilege role field indicates highest level
+    // matching proposed algorithms. The maximum privilege level the session
+    // can take is set to Administrator level. In the RAKP12 command sequence
+    // the session maximum privilege role is set again based on the user's
+    // permitted privilege level.
+    if (!request->maxPrivLevel)
+    {
+        priv = session::Privilege::ADMIN;
+    }
+    else
+    {
+        priv = static_cast<session::Privilege>(request->maxPrivLevel);
+    }
+
     // Check for valid Confidentiality Algorithms
     if (!cipher::crypt::Interface::isAlgorithmSupported(
             static_cast<cipher::crypt::Algorithms>(request->confAlgo)))
@@ -54,8 +70,7 @@
         session =
             std::get<session::Manager&>(singletonPool)
                 .startSession(
-                    endian::from_ipmi<>(request->remoteConsoleSessionID),
-                    static_cast<session::Privilege>(request->maxPrivLevel),
+                    endian::from_ipmi<>(request->remoteConsoleSessionID), priv,
                     static_cast<cipher::rakp_auth::Algorithms>(
                         request->authAlgo),
                     static_cast<cipher::integrity::Algorithms>(
@@ -73,7 +88,7 @@
 
     response->messageTag = request->messageTag;
     response->status_code = static_cast<uint8_t>(RAKP_ReturnCode::NO_ERROR);
-    response->maxPrivLevel = static_cast<uint8_t>(session->curPrivLevel);
+    response->maxPrivLevel = static_cast<uint8_t>(session->reqMaxPrivLevel);
     response->remoteConsoleSessionID = request->remoteConsoleSessionID;
     response->managedSystemSessionID =
         endian::to_ipmi<>(session->getBMCSessionID());
diff --git a/command/rakp12.cpp b/command/rakp12.cpp
index 17a7483..59ca9e3 100644
--- a/command/rakp12.cpp
+++ b/command/rakp12.cpp
@@ -136,7 +136,8 @@
     {
         session->curPrivLevel = session::Privilege::USER;
     }
-    session->reqMaxPrivLevel = request->req_max_privilege_level;
+    session->reqMaxPrivLevel =
+        static_cast<session::Privilege>(request->req_max_privilege_level);
     if (request->user_name_len == 0)
     {
         // Bail out, if user name is not specified.
diff --git a/command/rakp34.cpp b/command/rakp34.cpp
index 10c67fa..370c132 100644
--- a/command/rakp34.cpp
+++ b/command/rakp34.cpp
@@ -126,7 +126,7 @@
     auto rcSessionID = endian::to_ipmi(session->getRCSessionID());
 
     // Session Privilege Level
-    auto sessPrivLevel = session->reqMaxPrivLevel;
+    auto sessPrivLevel = static_cast<uint8_t>(session->reqMaxPrivLevel);
 
     // User Name Length Byte
     auto userLength = static_cast<uint8_t>(session->userName.size());
diff --git a/command/session_cmds.cpp b/command/session_cmds.cpp
index 3312c92..a6b4adb 100644
--- a/command/session_cmds.cpp
+++ b/command/session_cmds.cpp
@@ -32,8 +32,8 @@
         response->newPrivLevel = static_cast<uint8_t>(session->curPrivLevel);
         return outPayload;
     }
-    if (reqPrivilegeLevel >
-        (session->reqMaxPrivLevel & session::reqMaxPrivMask))
+    if (reqPrivilegeLevel > (static_cast<uint8_t>(session->reqMaxPrivLevel) &
+                             session::reqMaxPrivMask))
     {
         // Requested level exceeds Channel and/or User Privilege Limit
         response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
diff --git a/session.hpp b/session.hpp
index bf136e3..bc48971 100644
--- a/session.hpp
+++ b/session.hpp
@@ -116,7 +116,7 @@
      * @param[in] priv - Privilege Level requested in the Command
      */
     Session(SessionID inRemoteConsoleSessID, Privilege priv) :
-        curPrivLevel(priv), bmcSessionID(crypto::prng::rand()),
+        reqMaxPrivLevel(priv), bmcSessionID(crypto::prng::rand()),
         remoteConsoleSessionID(inRemoteConsoleSessID)
     {
     }
@@ -270,7 +270,7 @@
     /**
      * @brief Session's Requested Maximum Privilege Level
      */
-    uint8_t reqMaxPrivLevel;
+    Privilege reqMaxPrivLevel;
 
     SequenceNumbers sequenceNums;  // Session Sequence Numbers
     State state = State::INACTIVE; // Session State