Dropbears,
I submitted a patch to enhance the dropbear SSH server to handle the
Linux-PAM "expired password dialog". That is, if you ssh into a system
running the dropbear SSH server and configured to use Linux PAM and your
password is expired, this patch enhances the SSH server so you can
change your password while logging in.
I believe this feature will become more important to small devices
because of increased security concerns. Specifically, if a device is
created with a default ssh password, it is too easy for an attacker to
learn that password and gain access to the device. However, if that
password is pre-expired (such as with the `passwd --expire USERNAME`
command), the password must be changed before the device can be
accessed; that encourages folks to change the password away from the
default, so the attackers won't be able to access the device.
For example, California Law SB-327
(https://leginfo.legislature.ca.gov/faces/billTextClient.xhtml?bill_id=201720180SB327)
title 1.81.26 ("Security of Connected Devices") paragraph
1798.91.04. (b) (2) states (excerpted): it shall be deemed a reasonable
security feature [if] ... the device contains a security feature that
requires a user to generate a new means of authentication before access
is granted to the device for the first time.
That means you need to set or change the password before you can use the
device.
A use case is:
1. Someone creates a device which uses the dropbear SSH server, and
provisions the device with a username and default password, and
administratively expires the password.
2. A user installs the device and tries to use it. They are required to
change its password the first time they attempt to access it.
3. After this point, the attacker cannot access the device with its
default password.
Anyway, that's my motivation for making this patch.
This is a refresh of a previous patch discussed on the dropbear mailing
list:
https://lists.ucc.gu.uwa.edu.au/pipermail/dropbear/2016q2/thread.html in
threads titled "dropbear and PAM_NEW_AUTHTOK_REQ" and "[PATCH 1/2]
Support changing expired passwords".
This patch is substantially the same as the previous patch.
I did not make the corresponding change to the SSH client because I am
not using it.
Here is a code walkthrough to help explain the changes.
The scenario involves:
- A user who invokes the "ssh" command.
- The client "ssh" program.
- The dropbear "ssh" server.
- The Linux PAM implementation.
The sequence is:
1. A user directs their SSH client to login to the dropbear SSH server.
2. The ssh client passes the username and password to the dropbear ssh
server in a SSH_MSG_USERAUTH_REQUEST per RFC 4252.
3. The dropbear ssh server response to the client indicates the password
is expired. ==> dropbear is enhanced with a new message for this.
Specifically, return code PAM_NEW_AUTHTOK_REQD means that everything is
okay, except the password is expired and must be changed. Changed code
in svr-authpam.c function svr_auth_pam() handles this condition by
calling the new send_msg_userauth_chauthtok() function.
4. The SSH client prompts the user for a new password, and sends another
SSH_MSG_USERAUTH_REQUEST to the SSH server, this time with the fifth
element TRUE to indicate a password change request.
5. The dropbear ssh server changes the user's password, and the ssh
connection continues. ==> dropbear is enhanced to invoke pam_chauthtok
("change password") to handle this request.
This detailed code walkthrough begins at the last step. Referring to
the patched code:
- The SSH_MSG_USERAUTH_REQUEST flows into the dropbear SSH server, is
decoded partially, and control is passed into svr-authpam.c function
svr_auth_pam().
- The client_request_changepw boolean and existing password are read.
- If client_request_changepw==true, the new password is also read.
- Both passwords are stored in the UserData. (This is eventually passed
into pamConvFunc() as the appdata_ptr parameter via the call to
pam_start(..., pamConv, ...)).
- The pam_start and pam_authenticate functions are called as usual.
- If client_request_changepw==true, we invoke PAM pam_chauthtok() to
change the password. The call to pam_chauthtok() does not use the
PAM_CHANGE_EXPIRED_AUTHTOK flag, making this an unconditional request.
That is, if the SSH client requests a password change, we will
definitely call PAM to change the password.
- As part of its processing, the pam_chauthtok() function calls back
into the srv-authpam.c pamConvFunc() to obtain the new password. It
passes in a PAM_PROMPT_ECHO_OFF message like "Enter new password:". The
patch enhances this function to return the new password which it gets
from the userData set up by svr_auth_pam().
- If everything goes well, pam_chauthtok takes care of writing that
password into the /etc/passwd file.
- If not, PAM error codes are handled correctly.
Notes:
- The unnecessary m_burn(userDatap->passwd, ...) was removed, as it is
an alias of svr_auth_pam / password, and cleanup is performed by
svr_auth_pam at the cleanup label. This is where the strdup'd old and
new passwords are freed.
- The call to PAM pam_start() identifies the service_name of "sshd"
which affects the config files PAM uses to process dropbear requests.
The /etc/pam.d/sshd config file may need to be changed to tell PAM that
the sshd service should be allowed to change passwords. For example,
add an entry in the /etc/pam.d/ config files for the "sshd" service and
the "password" type, like this: sshd password include common-password.
- Joseph