Implement Redfish PasswordChangeRequired
This implements the Redfish PasswordChangeRequired handling. See
section 13.3.7.1 "Password change required handling" in the 1.9.1 spec:
https://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.9.1.pdf
These portions of the spec are implemented:
- Authenticatation with a correct but expired password creates a
session:
- The session is restricted to the ConfigureSelf privilege which
allows a user to change their own password (via GET and PATCH
Password for their own account). Support for the ConfigureSelf
privilege is already in BMCWeb.
- The session object has the PasswordChangeRequired message.
- All other operations respond with http status code 403 Forbidden
and include the PasswordChangeRequired message.
- The ManagerAccount (URI /redfish/v1/AccountService/Accounts/USER)
PasswordChangeRequired property is implemented for local accounts
but not present for remote accounts.
This has the following additional behavior:
The PasswordChangeRequired property is updated at the start of each new
REST operation, even within an existing session. This behavior
implements a "dynamic" PasswordChangeRequired handling that responds to
changes to the underlying "password expired" status. Specifically:
- Sessions restricted by the PasswordChangeRequired handling lose that
restriction when the underlying account password is changed.
- Sessions become subject to the PasswordChangeRequired handling
restrictions whenever the underlying account password expires.
- The mechanism is to check if the password is expired at the start of
every new REST API operation, effectively updating the ManagerAccount
PasswordChangeRequired property each time. This makes BMCWeb
responsive to changes in the underlying account due to other activity
on the BMC.
Notes:
1. Note that when an account password status is changed (for example,
the password becomes expired or is changed) and that account has
active sessions, those sessions remain. They are not deleted. Any
current operations are allowed to complete. Subsequent operations
with that session pick up the new password status.
2. This does not implement OWASP recommendations which call for sessions
to be dropped when there is a significant change to the underlying
account. For example, when the password is changed, the password
becomes expired, or when the account's Role changes. OWASP's
recommendation is due to the session fixation vulnerability. See the
OWASP Session Management Cheat Sheet section "Renew the Session ID
After Any Privilege Level Change":
https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#renew-the-session-id-after-any-privilege-level-change
BMCWeb protects against session fixation vulnerabilities because it
always regenerates new session IDs when successful authentication
creates a new session.
3. Users authenticating via mTLS are not subject to the
PasswordChangeRequired behavior because mTLS takes precedence over
password-based authentication.
Tested:
0. Setup:
- The `passwd --expire USERNAME` command was used to expire
passwords. The `chage USER` command was also used.
- The following were used to change the password: Redfish API,
passwd command, and the SSH password change dialog.
- Tested the following via Basic Auth, /login, and Redfish login
(except where Basic Auth does not create a persistent session).
- Only local user account were tested.
- Did not test authentication via mTLS or with LDAP users.
1. When the password is not expired, authentication behaves as usual
for both correct and incorrect passwords.
2. When the password is incorrect and expired, authentication fails as
usual.
3. When the password is correct but expired:
A. A session is created and has the PasswordChangeRequired message.
B. That session cannot access resources that require Login privilege
and the 403 message contains the PasswordChangeRequired message.
C. That session can be used to GET the user's account, PATCH the
Password, and DELETE the session object.
D. The account PasswordChangeRequired reports true.
4. While a session is established, try expiring and changing
(unexpiring) the password using various mechanisms. Ensure both the
session object and the ManagerAccount PasswordChangeRequired property
report the correct condition, and ensure PasswordChangeRequired
handling (restricting operations to ConfigureSelf when
PasswordChangeRequired is true) is applied correctly.
Signed-off-by: Joseph Reynolds <joseph-reynolds@charter.net>
Change-Id: Iedc61dea8f949e4b182e14dc189de02d1f74d3e8
diff --git a/redfish-core/include/node.hpp b/redfish-core/include/node.hpp
index 9086f1e..a6e1e27 100644
--- a/redfish-core/include/node.hpp
+++ b/redfish-core/include/node.hpp
@@ -169,8 +169,8 @@
res.end();
}
- /* @brief Would the operation be allowed if the user did not have
- * the ConfigureSelf Privilege?
+ /* @brief Would the operation be allowed if the user did not have the
+ * ConfigureSelf Privilege? Also honors session.isConfigureSelfOnly.
*
* @param req the request
*
@@ -181,9 +181,18 @@
const std::string& userRole = req.userRole;
BMCWEB_LOG_DEBUG << "isAllowedWithoutConfigureSelf for the role "
<< req.userRole;
- Privileges effectiveUserPrivileges =
- redfish::getUserPrivileges(userRole);
- effectiveUserPrivileges.resetSinglePrivilege("ConfigureSelf");
+ Privileges effectiveUserPrivileges;
+ if (req.session && req.session->isConfigureSelfOnly)
+ {
+ // The session has no privileges because it is limited to
+ // configureSelfOnly and we are disregarding that privilege.
+ // Note that some operations do not require any privilege.
+ }
+ else
+ {
+ effectiveUserPrivileges = redfish::getUserPrivileges(userRole);
+ effectiveUserPrivileges.resetSinglePrivilege("ConfigureSelf");
+ }
const auto& requiredPrivilegesIt = entityPrivileges.find(req.method());
return (requiredPrivilegesIt != entityPrivileges.end()) &&
isOperationAllowedWithPrivileges(requiredPrivilegesIt->second,