diff options
-rw-r--r-- | http/http_connection.hpp | 29 | ||||
-rw-r--r-- | http/http_request.hpp | 2 | ||||
-rw-r--r-- | include/authorization.hpp | 9 | ||||
-rw-r--r-- | include/login_routes.hpp | 2 | ||||
-rw-r--r-- | include/persistent_data.hpp | 1 | ||||
-rw-r--r-- | redfish-core/lib/redfish_sessions.hpp | 9 | ||||
-rw-r--r-- | static/redfish/v1/JsonSchemas/OemSession/index.json | 6 | ||||
-rw-r--r-- | static/redfish/v1/schema/OemSession_v1.xml | 4 |
8 files changed, 41 insertions, 21 deletions
diff --git a/http/http_connection.hpp b/http/http_connection.hpp index ec8e9d5233..6610beec9f 100644 --- a/http/http_connection.hpp +++ b/http/http_connection.hpp @@ -241,7 +241,8 @@ class Connection : session = persistent_data::SessionStore::getInstance() .generateUserSession( - sslUser, persistent_data::PersistenceType::TIMEOUT); + sslUser, persistent_data::PersistenceType::TIMEOUT, + false, req->ipAddress.to_string()); if (auto sp = session.lock()) { BMCWEB_LOG_DEBUG << this @@ -278,6 +279,10 @@ class Connection : { startDeadline(0); + + // Fetch the client IP address + readClientIp(); + // TODO(ed) Abstract this to a more clever class with the idea of an // asynchronous "start" if constexpr (std::is_same_v<Adaptor, @@ -319,7 +324,7 @@ class Connection : BMCWEB_LOG_INFO << "Request: " << " " << this << " HTTP/" << req->version() / 10 << "." << req->version() % 10 << ' ' << req->methodString() - << " " << req->target(); + << " " << req->target() << " " << req->ipAddress; needToCallAfterHandlers = false; @@ -461,6 +466,26 @@ class Connection : res.completeRequestHandler = nullptr; } + void readClientIp() + { + boost::system::error_code ec; + BMCWEB_LOG_DEBUG << "Fetch the client IP address"; + boost::asio::ip::tcp::endpoint endpoint = + boost::beast::get_lowest_layer(adaptor).remote_endpoint(ec); + + if (ec) + { + // If remote endpoint fails keep going. "ClientOriginIPAddress" + // will be empty. + BMCWEB_LOG_ERROR << "Failed to get the client's IP Address. ec : " + << ec; + } + else + { + req->ipAddress = endpoint.address(); + } + } + private: void doReadHeaders() { diff --git a/http/http_request.hpp b/http/http_request.hpp index e5c0c9e982..8bcce064db 100644 --- a/http/http_request.hpp +++ b/http/http_request.hpp @@ -4,6 +4,7 @@ #include "sessions.hpp" #include <boost/asio/io_context.hpp> +#include <boost/asio/ip/address.hpp> #include <boost/beast/http/message.hpp> #include <boost/beast/http/string_body.hpp> #include <boost/beast/websocket.hpp> @@ -24,6 +25,7 @@ struct Request const std::string& body; boost::asio::io_context* ioService{}; + boost::asio::ip::address ipAddress{}; std::shared_ptr<persistent_data::UserSession> session; diff --git a/include/authorization.hpp b/include/authorization.hpp index e965508e08..0f73e967cb 100644 --- a/include/authorization.hpp +++ b/include/authorization.hpp @@ -35,7 +35,8 @@ static void cleanupTempSession(Request& req) } static std::shared_ptr<persistent_data::UserSession> - performBasicAuth(std::string_view auth_header) + performBasicAuth(const boost::asio::ip::address& clientIp, + std::string_view auth_header) { BMCWEB_LOG_DEBUG << "[AuthMiddleware] Basic authentication"; @@ -60,6 +61,8 @@ static std::shared_ptr<persistent_data::UserSession> std::string pass = authData.substr(separator); BMCWEB_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user; + BMCWEB_LOG_DEBUG << "[AuthMiddleware] User IPAddress: " + << clientIp.to_string(); int pamrc = pamAuthenticateUser(user, pass); bool isConfigureSelfOnly = pamrc == PAM_NEW_AUTHTOK_REQD; @@ -76,7 +79,7 @@ static std::shared_ptr<persistent_data::UserSession> // calling directly into pam for every request return persistent_data::SessionStore::getInstance().generateUserSession( user, persistent_data::PersistenceType::SINGLE_REQUEST, - isConfigureSelfOnly); + isConfigureSelfOnly, clientIp.to_string()); } static std::shared_ptr<persistent_data::UserSession> @@ -269,7 +272,7 @@ static void authenticate( else if (boost::starts_with(authHeader, "Basic ") && authMethodsConfig.basic) { - req.session = performBasicAuth(authHeader); + req.session = performBasicAuth(req.ipAddress, authHeader); } } } diff --git a/include/login_routes.hpp b/include/login_routes.hpp index 1f7b35a3b4..6879de0d47 100644 --- a/include/login_routes.hpp +++ b/include/login_routes.hpp @@ -141,7 +141,7 @@ inline void requestRoutes(App& app) .generateUserSession( username, persistent_data::PersistenceType::TIMEOUT, - isConfigureSelfOnly); + isConfigureSelfOnly, req.ipAddress.to_string()); if (looksLikePhosphorRest) { diff --git a/include/persistent_data.hpp b/include/persistent_data.hpp index 19c424a202..0ff0c7e1df 100644 --- a/include/persistent_data.hpp +++ b/include/persistent_data.hpp @@ -193,6 +193,7 @@ class ConfigFile {"session_token", p.second->sessionToken}, {"username", p.second->username}, {"csrf_token", p.second->csrfToken}, + {"client_ip", p.second->clientIp}, #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE {"client_id", p.second->clientId}, #endif diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp index e3259895d2..c38f1026d2 100644 --- a/redfish-core/lib/redfish_sessions.hpp +++ b/redfish-core/lib/redfish_sessions.hpp @@ -60,15 +60,15 @@ class Sessions : public Node res.jsonValue["UserName"] = session->username; res.jsonValue["@odata.id"] = "/redfish/v1/SessionService/Sessions/" + session->uniqueId; - res.jsonValue["@odata.type"] = "#Session.v1_0_2.Session"; + res.jsonValue["@odata.type"] = "#Session.v1_3_0.Session"; res.jsonValue["Name"] = "User Session"; res.jsonValue["Description"] = "Manager User Session"; + res.jsonValue["ClientOriginIPAddress"] = session->clientIp; +#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE res.jsonValue["Oem"]["OpenBMC"]["@odata.type"] = "#OemSession.v1_0_0.Session"; -#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE res.jsonValue["Oem"]["OpenBMC"]["ClientID"] = session->clientId; #endif - res.jsonValue["Oem"]["OpenBMC"]["ClientOriginIP"] = session->clientIp; res.end(); } @@ -174,7 +174,6 @@ class SessionCollection : public Node std::string password; std::optional<nlohmann::json> oemObject; std::string clientId; - std::string clientIp; if (!json_util::readJson(req, res, "UserName", username, "Password", password, "Oem", oemObject)) { @@ -231,7 +230,7 @@ class SessionCollection : public Node std::shared_ptr<persistent_data::UserSession> session = persistent_data::SessionStore::getInstance().generateUserSession( username, persistent_data::PersistenceType::TIMEOUT, - isConfigureSelfOnly, clientId, clientIp); + isConfigureSelfOnly, clientId, req.ipAddress.to_string()); res.addHeader("X-Auth-Token", session->sessionToken); res.addHeader("Location", "/redfish/v1/SessionService/Sessions/" + session->uniqueId); diff --git a/static/redfish/v1/JsonSchemas/OemSession/index.json b/static/redfish/v1/JsonSchemas/OemSession/index.json index c80e34003c..8eefd952f3 100644 --- a/static/redfish/v1/JsonSchemas/OemSession/index.json +++ b/static/redfish/v1/JsonSchemas/OemSession/index.json @@ -28,12 +28,6 @@ "readonly": true, "type" : "string" }, - "ClientOriginIP" : { - "description": "The IP address where the Session was created from.", - "longDescription": "This property shall contain the IP address where the client created the session from.", - "readonly": true, - "type": "string" - }, "type": "object" } } diff --git a/static/redfish/v1/schema/OemSession_v1.xml b/static/redfish/v1/schema/OemSession_v1.xml index cc74848b81..f02f8617eb 100644 --- a/static/redfish/v1/schema/OemSession_v1.xml +++ b/static/redfish/v1/schema/OemSession_v1.xml @@ -32,10 +32,6 @@ <Annotation Term="OData.Description" String="The Id of the client creating this session."/> <Annotation Term="OData.LongDescription" String="This will be the unique identifier set by the client."/> </Property> - <Property Name="ClientOriginIP" Type="Edm.String"> - <Annotation Term="OData.Description" String="The IP address where the Session was created from."/> - <Annotation Term="OData.LongDescription" String="This property shall contain the IP address where the client created the session from."/> - </Property> </EntityType> </Schema> |