File pam_unix-allow-empty-passwords-with-non-empty-hashes.patch of Package pam.36767

From 8d0c575336ad301cd14e16ad2fdec6fe621764b8 Mon Sep 17 00:00:00 2001
From: Sergei Trofimovich <slyich@gmail.com>
Date: Thu, 28 Mar 2024 21:58:35 +0000
Subject: [PATCH] pam_unix: allow empty passwords with non-empty hashes

Before the change pam_unix has different behaviours for a user with
empty password for these two `/etc/shadow` entries:

    nulloktest:$6$Yy4ty2jJ$bsVQWo8qlXC6UHq1/qTC3UR60ZJKmKApJ3Wj7DreAy8FxlVKtlDnplFQ7jMLVlDqordE7e4t49GvTb.aI59TP0:1::::::
    nulloktest::1::::::

The entry with a hash was rejected and the entry without was accepted.

The rejection happened because 9e74e90147c "pam_unix: avoid determining
if user exists" introduced the following rejection check (slightly
simplified):

        ...
        } else if (p[0] == '\0' && nullok) {
                if (hash[0] != '\0') {
                        retval = PAM_AUTH_ERR;
                }

We should not reject the user with a hash assuming it's non-empty.
The change does that by pushing empty password check into
`verify_pwd_hash()`.

`NixOS` generates such hashed entries for empty passwords as if they
were non-empty using the following perl code:

    sub hashPassword {
        my ($password) = @_;
        my $salt = "";
        my @chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
        $salt .= $chars[rand 64] for (1..8);
        return crypt($password, '$6$' . $salt . '$');
    }

Resolves: https://github.com/linux-pam/linux-pam/issues/758
Fixes: 9e74e90147c "pam_unix: avoid determining if user exists"
Signed-off-by: Sergei Trofimovich <slyich@gmail.com>
---
 modules/pam_unix/passverify.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index 30045333..1c83f1aa 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -76,9 +76,13 @@ PAMH_ARG_DECL(int verify_pwd_hash,
 
 	strip_hpux_aging(hash);
 	hash_len = strlen(hash);
-	if (!hash_len) {
+
+	if (p && p[0] == '\0' && !nullok) {
+		/* The passed password is empty */
+		retval = PAM_AUTH_ERR;
+	} else if (!hash_len) {
 		/* the stored password is NULL */
-		if (nullok) { /* this means we've succeeded */
+		if (p && p[0] == '\0' && nullok) { /* this means we've succeeded */
 			D(("user has empty password - access granted"));
 			retval = PAM_SUCCESS;
 		} else {
2.47.0

openSUSE Build Service is sponsored by