diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/sessions.hpp | 19 | ||||
-rw-r--r-- | include/token_authorization_middleware.hpp | 19 |
2 files changed, 29 insertions, 9 deletions
diff --git a/include/sessions.hpp b/include/sessions.hpp index 9d24327eab..a7ffe28921 100644 --- a/include/sessions.hpp +++ b/include/sessions.hpp @@ -45,6 +45,15 @@ struct UserSession std::chrono::time_point<std::chrono::steady_clock> lastUpdated; PersistenceType persistence; bool cookieAuth = false; + bool isConfigureSelfOnly = false; + + // There are two sources of truth for isConfigureSelfOnly: + // 1. When pamAuthenticateUser() returns PAM_NEW_AUTHTOK_REQD. + // 2. D-Bus User.Manager.GetUserInfo property UserPasswordExpired. + // These should be in sync, but the underlying condition can change at any + // time. For example, a password can expire or be changed outside of + // bmcweb. The value stored here is updated at the start of each + // operation and used as the truth within bmcweb. /** * @brief Fills object with data from UserSession's JSON representation @@ -196,7 +205,8 @@ class SessionStore public: std::shared_ptr<UserSession> generateUserSession( const std::string_view username, - PersistenceType persistence = PersistenceType::TIMEOUT) + PersistenceType persistence = PersistenceType::TIMEOUT, + bool isConfigureSelfOnly = false) { // TODO(ed) find a secure way to not generate session identifiers if // persistence is set to SINGLE_REQUEST @@ -244,9 +254,10 @@ class SessionStore } } - auto session = std::make_shared<UserSession>(UserSession{ - uniqueId, sessionToken, std::string(username), csrfToken, - std::chrono::steady_clock::now(), persistence}); + auto session = std::make_shared<UserSession>( + UserSession{uniqueId, sessionToken, std::string(username), + csrfToken, std::chrono::steady_clock::now(), + persistence, false, isConfigureSelfOnly}); auto it = authTokens.emplace(std::make_pair(sessionToken, session)); // Only need to write to disk if session isn't about to be destroyed. needWrite = persistence == PersistenceType::TIMEOUT; diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp index aaa1325b7a..ccea929f6f 100644 --- a/include/token_authorization_middleware.hpp +++ b/include/token_authorization_middleware.hpp @@ -138,7 +138,9 @@ class Middleware BMCWEB_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user; - if (pamAuthenticateUser(user, pass) != PAM_SUCCESS) + int pamrc = pamAuthenticateUser(user, pass); + bool isConfigureSelfOnly = pamrc == PAM_NEW_AUTHTOK_REQD; + if ((pamrc != PAM_SUCCESS) && !isConfigureSelfOnly) { return nullptr; } @@ -150,7 +152,8 @@ class Middleware // This whole flow needs to be revisited anyway, as we can't be // calling directly into pam for every request return persistent_data::SessionStore::getInstance().generateUserSession( - user, crow::persistent_data::PersistenceType::SINGLE_REQUEST); + user, crow::persistent_data::PersistenceType::SINGLE_REQUEST, + isConfigureSelfOnly); } const std::shared_ptr<crow::persistent_data::UserSession> @@ -397,14 +400,20 @@ template <typename... Middlewares> void requestRoutes(Crow<Middlewares...>& app) if (!username.empty() && !password.empty()) { - if (pamAuthenticateUser(username, password) != PAM_SUCCESS) + int pamrc = pamAuthenticateUser(username, password); + bool isConfigureSelfOnly = pamrc == PAM_NEW_AUTHTOK_REQD; + if ((pamrc != PAM_SUCCESS) && !isConfigureSelfOnly) { res.result(boost::beast::http::status::unauthorized); } else { - auto session = persistent_data::SessionStore::getInstance() - .generateUserSession(username); + auto session = + persistent_data::SessionStore::getInstance() + .generateUserSession( + username, + crow::persistent_data::PersistenceType::TIMEOUT, + isConfigureSelfOnly); if (looksLikePhosphorRest) { |