FS#68410 - [pam] Incompatibility with libxcrypt-generated passwords

Attached to Project: Arch Linux
Opened by Wilhelm Schuster (wlhlm) - Sunday, 25 October 2020, 09:46 GMT
Last edited by David Runge (dvzrv) - Wednesday, 19 April 2023, 13:17 GMT
Task Type Bug Report
Category Packages: Core
Status Closed
Assigned To Tobias Powalowski (tpowa)
David Runge (dvzrv)
Architecture All
Severity High
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 2
Private No

Details

Description:
It appears that [pam] can't handle password hashes generated using the default crypt(3) method (yescrypt). This is problematic when using tools that generate settings based on those defaults and don't hardcode a known working hash (for example sha512) such as [shadow] does currently in /etc/pam.d/.


Additional info:
* package versions:
* pam 1.4.0-3
* libxcrypt 4.4.17-1
* shadow 4.8.1-4
* systemd 246.6-1
* glibc 2.32-5

Steps to reproduce:
The problem originally manifested itself in that that I wasn't able to log in as root user after setting the password using `systemd-firstboot --force --root-password=`. In the following I've set the root password and subsequently tried to change to root using `su`:

$ sudo systemd-firstboot --force --root-password=root
/etc/passwd written
/etc/shadow written.
$ sudo grep "^root" /etc/shadow
root:$y$j9T$FB4E3r3ypNUldZO.aYuPN.$JtOaeKaEJp43qSocj5nMBeCweVjFon4MvsH4j42xZu9:18560::::::
$ su
Password:
su: Authentication failure

You can see that `systemd-firstboot` generated a yescrypt password hash (prefix $y$, more info in crypt(5)), unfortunately `su` fails after that. Here is the log output (with "audit" logging enabled in `/etc/pam.d/su`):

$ journalctl -b -r --no-hostname --no-pager
-- Logs begin at Mon 2019-09-16 20:41:18 CEST, end at Sun 2020-10-25 09:42:00 CET. --
Oct 25 09:42:00 su[375597]: FAILED SU (to root) rot13 on pts/12
Oct 25 09:41:58 kernel: audit: type=1100 audit(1603615318.651:1887): pid=375597 uid=1000 auid=1000 ses=1 msg='op=PAM:authentication grantors=? acct="root" exe="/usr/bin/su" hostname=pluto addr=? terminal=pts/12 res=failed'
Oct 25 09:41:58 audit[375597]: USER_AUTH pid=375597 uid=1000 auid=1000 ses=1 msg='op=PAM:authentication grantors=? acct="root" exe="/usr/bin/su" hostname=pluto addr=? terminal=pts/12 res=failed'
Oct 25 09:41:58 su[375597]: pam_unix(su:auth): authentication failure; logname= uid=1000 euid=0 tty=pts/12 ruser=rot13 rhost= user=root
Oct 25 09:41:53 su[375597]: pam_unix(su:auth): username [root] obtained
[...]

The log output doesn't say much. It almost looks like I just typed in the wrong password, but I can assure that I did not ;-). However, using one of the utilities included in [shadow] works as expected:

$ sudo sh -c 'echo "root:root" | chpasswd'
$ sudo grep "^root" /etc/shadow
root:$6$6QK5rOtEK6Sycxsf$JZ/dTd/fDgUbI72GFxtVRIVd0q1XYg29JjoVOq24A615Aycj.KqiFurbRqx1E6FEpckcHXfPb65jsskwKXW3f1:18560::::::
$ su
Password:
#

`chpasswd` generated a sha512 password hash (prefix $6$) and that works without fail.

Here is what I found out investigating why a password set by systemd-firstboot failed, but a password set using one of the tools provided by [shadow] (passwd, chpass, etc.) worked:

systemd-firstboot directly calls crypt(3) (recently provided by [libxcrypt] [1]) using libxcrypt's preferred hashing method, which is yescrypt at the moment. The resulting password hash is directly written into `/etc/shadow`. I have attached a small C program which essentially demonstrates how systemd-firstboot generates password hashes. The program can be compiled using `gcc -o crypt-test -lcrypt crypt-test.c`. The tools from [shadow] for example don't seem to call crypt(3) directly, but use pam. Consequently, their behaviour can be configured in `/etc/pam.d`:

$ cat /etc/pam.d/chpasswd
#%PAM-1.0
auth sufficient pam_rootok.so
auth required pam_unix.so
account required pam_unix.so
session required pam_unix.so
password required pam_unix.so sha512 shadow

In the last line you can see that chpasswd is configured to generate sha512 hashes. This is discussed in  FS#67393  and the intention is to remove this setting as it overwrites `/etc/login.defs`, but it's still there for now. For testing I can force yescrypt hashing as per pam_unix(5) to compare this with systemd-firstboot:

$ cat /etc/pam.d/chpasswd
#%PAM-1.0
auth sufficient pam_rootok.so
auth required pam_unix.so
account required pam_unix.so
session required pam_unix.so
password required pam_unix.so yescrypt shadow audit
$ sudo sh -c 'echo "root:root" | chpasswd'
chpasswd: (user root) pam_chauthtok() failed, error:
Memory buffer error
chpasswd: (line 1, user root) password not changed
$ journalctl -b -r --no-hostname --no-pager
[...]
Oct 25 10:28:58 sudo[376104]: pam_unix(sudo:session): session closed for user root
Oct 25 10:28:58 audit[376107]: USER_CHAUTHTOK pid=376107 uid=0 auid=1000 ses=1 msg='op=PAM:chauthtok grantors=? acct="root" exe="/usr/bin/chpasswd" hostname=pluto addr=? terminal=pts/12 res=failed'
Oct 25 10:28:58 chpasswd[376107]: pam_unix(chpasswd:chauthtok): crypt() failure or out of memory for password
Oct 25 10:28:58 chpasswd[376107]: pam_unix(chpasswd:chauthtok): Algo yescrypt not supported by the crypto backend.
Oct 25 10:28:58 chpasswd[376107]: pam_unix(chpasswd:chauthtok): username [root] obtained
Oct 25 10:28:58 chpasswd[376107]: pam_unix(chpasswd:chauthtok): username [root] obtained
Oct 25 10:28:58 sudo[376104]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
Oct 25 10:28:58 sudo[376104]: rot13 : TTY=pts/12 ; PWD=/home/rot13 ; USER=root ; COMMAND=/usr/bin/sh -c echo "root:root" | chpasswd
[...]

You can see that forcing yescrypt directly via `/etc/pam.d/chpasswd` results in chpasswd being unable to set the new password. "Memory buffer error" seems to be a bogus message here, looking at the logs, we can find the real reason for the failure: "Algo yescrypt not supported by the crypto backend."

Suggested resolution:
Update [pam] to support yescrypt password hashes. Alternatively update libxcrypt's crypt(3) to generate sha512 password hashes by default so that tools that rely on crypt(3)'s default settings are able to generate working password hashes. The latter suggestion is less desired as sha512 seems to generally be regarded as a lesser password hashing method compared to yescrypt.
This task depends upon

Closed by  David Runge (dvzrv)
Wednesday, 19 April 2023, 13:17 GMT
Reason for closing:  Fixed
Comment by Wilhelm Schuster (wlhlm) - Sunday, 25 October 2020, 09:51 GMT
Looks like flyspray removed a lot of whitespaces. :-/ I hope this is still readable.
Comment by Wilhelm Schuster (wlhlm) - Sunday, 25 October 2020, 09:57 GMT
Looks like the libxcrypt rebuild is still ongoing:
https://www.archlinux.org/todo/libxcrypt-rebuild/

systemd and shadow have been rebuild, while pam has not. This probably explains the incompatibility. I suggest upgrading these packages in lockstep the next time a similar rebuild is necessary. It looks like the shadow rebuild has worked out without problems (luckily) since it's hardcoded to the more compatible sha512 method as per  FS#67393 .
Comment by David Runge (dvzrv) - Thursday, 20 October 2022, 08:48 GMT
@wlhlm: I've also activated yescrypt support in shadow (see https://bugs.archlinux.org/task/67393#comment211947).

Is this issue still showing today?
Comment by Wilhelm Schuster (wlhlm) - Wednesday, 19 April 2023, 11:23 GMT
This issue is no longer showing on my end. (sorry for late response)
Comment by David Runge (dvzrv) - Wednesday, 19 April 2023, 13:17 GMT
No worries. Thanks for getting back!

Loading...