RMCP+ login support with privilege
Implementation of RMCP login support with appropriate
privilege level.
Unit Test:
1. Verified that user is able to login without any issues
2. Privilege of the user is minimum of requested, user & channel
3. Unable to set higher privilege using Set session commands
Change-Id: I5e9ef21dfc1f1b50aa815562a3a65d90c434877c
Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
diff --git a/command/rakp12.cpp b/command/rakp12.cpp
index b4842b2..5384ab3 100644
--- a/command/rakp12.cpp
+++ b/command/rakp12.cpp
@@ -11,6 +11,8 @@
#include <cstring>
#include <iomanip>
#include <iostream>
+#include <user_channel/channel_layer.hpp>
+#include <user_channel/user_layer.hpp>
namespace command
{
@@ -61,15 +63,6 @@
session->userName.assign(request->user_name, request->user_name_len);
- // Validate the user name if the username is provided
- if (request->user_name_len &&
- (session->userName != cipher::rakp_auth::userName))
- {
- response->rmcpStatusCode =
- static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
- return outPayload;
- }
-
// Update transaction time
session->updateLastTransactionTime();
@@ -129,6 +122,80 @@
return outPayload;
}
+ session->reqMaxPrivLevel = request->req_max_privilege_level;
+ session->curPrivLevel = static_cast<session::Privilege>(
+ request->req_max_privilege_level & session::reqMaxPrivMask);
+ if (((request->req_max_privilege_level & userNameOnlyLookupMask) !=
+ userNameOnlyLookup) ||
+ (request->user_name_len == 0))
+ {
+ // Skip privilege based lookup for security purpose
+ response->rmcpStatusCode =
+ static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
+ return outPayload;
+ }
+
+ // Perform user name based lookup
+ std::string userName(request->user_name, request->user_name_len);
+ std::string passwd;
+ uint8_t userId = ipmi::ipmiUserGetUserId(userName);
+ if (userId == ipmi::invalidUserId)
+ {
+ response->rmcpStatusCode =
+ static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
+ return outPayload;
+ }
+ // check user is enabled before proceeding.
+ bool userEnabled = false;
+ ipmi::ipmiUserCheckEnabled(userId, userEnabled);
+ if (!userEnabled)
+ {
+ response->rmcpStatusCode =
+ static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
+ return outPayload;
+ }
+ // Get the user password for RAKP message authenticate
+ passwd = ipmi::ipmiUserGetPassword(userName);
+ if (passwd.empty())
+ {
+ response->rmcpStatusCode =
+ static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
+ return outPayload;
+ }
+ ipmi::PrivAccess userAccess{};
+ ipmi::ChannelAccess chAccess{};
+ // TODO Replace with proper calls.
+ uint8_t chNum = static_cast<uint8_t>(ipmi::EChannelID::chanLan1);
+ // Get channel based access information
+ if ((ipmi::ipmiUserGetPrivilegeAccess(userId, chNum, userAccess) !=
+ IPMI_CC_OK) ||
+ (ipmi::getChannelAccessData(chNum, chAccess) != IPMI_CC_OK))
+ {
+ response->rmcpStatusCode =
+ static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
+ return outPayload;
+ }
+ session->chNum = chNum;
+ // minimum privilege of Channel / User / requested has to be used
+ // as session current privilege level
+ uint8_t minPriv = 0;
+ if (chAccess.privLimit < userAccess.privilege)
+ {
+ minPriv = chAccess.privLimit;
+ }
+ else
+ {
+ minPriv = userAccess.privilege;
+ }
+ if (session->curPrivLevel > static_cast<session::Privilege>(minPriv))
+ {
+ session->curPrivLevel = static_cast<session::Privilege>(minPriv);
+ }
+
+ std::fill(authAlgo->userKey.data(),
+ authAlgo->userKey.data() + authAlgo->userKey.size(), 0);
+ std::copy_n(passwd.c_str(), passwd.size(), authAlgo->userKey.data());
+
// Copy the Managed System Random Number to the Authentication Algorithm
std::copy_n(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN,
authAlgo->bmcRandomNum.begin());
@@ -139,15 +206,10 @@
std::advance(iter, BMC_GUID_LEN);
// Requested Privilege Level
- session->curPrivLevel =
- static_cast<session::Privilege>(request->req_max_privilege_level);
std::copy_n(&(request->req_max_privilege_level),
sizeof(request->req_max_privilege_level), iter);
std::advance(iter, sizeof(request->req_max_privilege_level));
- // Set Max Privilege to ADMIN
- session->maxPrivLevel = session::Privilege::ADMIN;
-
// User Name Length Byte
std::copy_n(&(request->user_name_len), sizeof(request->user_name_len),
iter);