summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch218
1 files changed, 218 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch
new file mode 100644
index 000000000..1ba584616
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch
@@ -0,0 +1,218 @@
+From aabe4718b8e6c1f7b91af29cbaf85d5fa1fa0a99 Mon Sep 17 00:00:00 2001
+From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+Date: Mon, 18 Oct 2021 22:55:38 +0530
+Subject: [PATCH] Add Support for privilege check in handleUpgrade
+
+This commit enables privilege check for user(s) in case of upgraded
+connections.
+Currently users with no privileges will also be able to access
+Websockets connections (Ex: KVM).
+
+Tested:
+ - websocket_test.py Passed
+ - Admin and Operator users were able to access KVM on WebUI
+ - Readonly User was unable to access KVM on WebUI
+
+Change-Id: Id9d33aeca24d8fafb2e9dcc28c46a48930740cd6
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+---
+ http/app.hpp | 2 +-
+ http/routing.hpp | 162 +++++++++++++++++++++++++++++++++++++++--------
+ 2 files changed, 136 insertions(+), 28 deletions(-)
+
+diff --git a/http/app.hpp b/http/app.hpp
+index c46dcf7..dd51eee 100644
+--- a/http/app.hpp
++++ b/http/app.hpp
+@@ -45,7 +45,7 @@ class App
+ }
+
+ template <typename Adaptor>
+- void handleUpgrade(const Request& req,
++ void handleUpgrade(Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ Adaptor&& adaptor)
+ {
+diff --git a/http/routing.hpp b/http/routing.hpp
+index acc99dc..e2a8fbb 100644
+--- a/http/routing.hpp
++++ b/http/routing.hpp
+@@ -1209,7 +1209,7 @@ class Router
+ }
+
+ template <typename Adaptor>
+- void handleUpgrade(const Request& req,
++ void handleUpgrade(Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ Adaptor&& adaptor)
+ {
+@@ -1277,32 +1277,140 @@ class Router
+ << "' " << static_cast<uint32_t>(req.method()) << " / "
+ << rules[ruleIndex]->getMethods();
+
+- // any uncaught exceptions become 500s
+- try
+- {
+- // Creating temporary response object to call handleUpgrade
+- // We cannot pass the asyncResp as it will be destroyed
+- // The response object is not initialized as handleUpgrade wouldn't
+- // be using this object
+- crow::Response resp;
+- rules[ruleIndex]->handleUpgrade(req, resp, std::move(adaptor));
+- }
+- catch (std::exception& e)
+- {
+- BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what();
+- asyncResp->res.result(
+- boost::beast::http::status::internal_server_error);
+- return;
+- }
+- catch (...)
+- {
+- BMCWEB_LOG_ERROR
+- << "An uncaught exception occurred. The type was unknown "
+- "so no information was available.";
+- asyncResp->res.result(
+- boost::beast::http::status::internal_server_error);
+- return;
+- }
++ crow::connections::systemBus->async_method_call(
++ [&req, asyncResp, &rules, ruleIndex, &adaptor](
++ const boost::system::error_code ec,
++ std::map<std::string, std::variant<bool, std::string,
++ std::vector<std::string>>>
++ userInfo) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "GetUserInfo failed...";
++ asyncResp->res.result(
++ boost::beast::http::status::internal_server_error);
++ return;
++ }
++
++ const std::string* userRolePtr = nullptr;
++ auto userInfoIter = userInfo.find("UserPrivilege");
++ if (userInfoIter != userInfo.end())
++ {
++ userRolePtr =
++ std::get_if<std::string>(&userInfoIter->second);
++ }
++
++ std::string userRole{};
++ if (userRolePtr != nullptr)
++ {
++ userRole = *userRolePtr;
++ BMCWEB_LOG_DEBUG << "userName = " << req.session->username
++ << " userRole = " << *userRolePtr;
++ }
++
++ bool* remoteUserPtr = nullptr;
++ auto remoteUserIter = userInfo.find("RemoteUser");
++ if (remoteUserIter != userInfo.end())
++ {
++ remoteUserPtr = std::get_if<bool>(&remoteUserIter->second);
++ }
++ if (remoteUserPtr == nullptr)
++ {
++ BMCWEB_LOG_ERROR
++ << "RemoteUser property missing or wrong type";
++ asyncResp->res.result(
++ boost::beast::http::status::internal_server_error);
++ return;
++ }
++ bool remoteUser = *remoteUserPtr;
++
++ bool passwordExpired = false; // default for remote user
++ if (!remoteUser)
++ {
++ bool* passwordExpiredPtr = nullptr;
++ auto passwordExpiredIter =
++ userInfo.find("UserPasswordExpired");
++ if (passwordExpiredIter != userInfo.end())
++ {
++ passwordExpiredPtr =
++ std::get_if<bool>(&passwordExpiredIter->second);
++ }
++ if (passwordExpiredPtr != nullptr)
++ {
++ passwordExpired = *passwordExpiredPtr;
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR
++ << "UserPasswordExpired property is expected for"
++ " local user but is missing or wrong type";
++ asyncResp->res.result(
++ boost::beast::http::status::internal_server_error);
++ return;
++ }
++ }
++
++ // Get the userprivileges from the role
++ redfish::Privileges userPrivileges =
++ redfish::getUserPrivileges(userRole);
++
++ // Set isConfigureSelfOnly based on D-Bus results. This
++ // ignores the results from both pamAuthenticateUser and the
++ // value from any previous use of this session.
++ req.session->isConfigureSelfOnly = passwordExpired;
++
++ // Modifyprivileges if isConfigureSelfOnly.
++ if (req.session->isConfigureSelfOnly)
++ {
++ // Remove allprivileges except ConfigureSelf
++ userPrivileges = userPrivileges.intersection(
++ redfish::Privileges{"ConfigureSelf"});
++ BMCWEB_LOG_DEBUG << "Operation limited to ConfigureSelf";
++ }
++
++ if (!rules[ruleIndex]->checkPrivileges(userPrivileges))
++ {
++ asyncResp->res.result(
++ boost::beast::http::status::forbidden);
++ if (req.session->isConfigureSelfOnly)
++ {
++ redfish::messages::passwordChangeRequired(
++ asyncResp->res,
++ "/redfish/v1/AccountService/Accounts/" +
++ req.session->username);
++ }
++ return;
++ }
++
++ req.userRole = userRole;
++
++ // any uncaught exceptions become 500s
++ try
++ {
++ crow::Response resp;
++ rules[ruleIndex]->handleUpgrade(req, resp,
++ std::move(adaptor));
++ }
++ catch (std::exception& e)
++ {
++ BMCWEB_LOG_ERROR << "An uncaught exception occurred: "
++ << e.what();
++ asyncResp->res.result(
++ boost::beast::http::status::internal_server_error);
++ return;
++ }
++ catch (...)
++ {
++ BMCWEB_LOG_ERROR
++ << "An uncaught exception occurred. The type was "
++ "unknown so no information was available.";
++ asyncResp->res.result(
++ boost::beast::http::status::internal_server_error);
++ return;
++ }
++ },
++ "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
++ "xyz.openbmc_project.User.Manager", "GetUserInfo",
++ req.session->username);
+ }
+
+ void handle(Request& req,
+--
+2.17.1
+