commit: 90e2a0cb4a5f3f7d712f6dcdf8926141b2453cd9
parent 84edf5725688c180bc0e34e8139612afc34d1dc9
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Mon, 29 Mar 2021 19:19:59 +0200
sys-apps/shadow: Prevent empty password
Diffstat:
3 files changed, 155 insertions(+), 32 deletions(-)
diff --git a/patches/sys-apps/shadow/0001-login-su-Treat-an-empty-passwd-field-as-invalid.patch b/patches/sys-apps/shadow/0001-login-su-Treat-an-empty-passwd-field-as-invalid.patch
@@ -0,0 +1,51 @@
+From 999a428a064222c4fba980baa3b061d39e23ed75 Mon Sep 17 00:00:00 2001
+From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
+Date: Sun, 14 Mar 2021 19:13:13 +0100
+Subject: [PATCH 1/2] login & su: Treat an empty passwd field as invalid
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Otherwise it's treated like the “require no password” clause while it probably
+should be treated like a normal su that can't validate anyway.
+
+A similar change should be done for USE_PAM.
+---
+ src/login.c | 4 ++++
+ src/su.c | 5 +++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/src/login.c b/src/login.c
+index 00508cd5..0c0b5c86 100644
+--- a/src/login.c
++++ b/src/login.c
+@@ -978,6 +978,10 @@ int main (int argc, char **argv)
+ || ('*' == user_passwd[0])) {
+ failed = true;
+ }
++ /* Treat empty password field as invalid */
++ if (strcmp (user_passwd, "") == 0) {
++ failed = true;
++ }
+ }
+
+ if (strcmp (user_passwd, SHADOW_PASSWD_STRING) == 0) {
+diff --git a/src/su.c b/src/su.c
+index fc0e826f..638f533f 100644
+--- a/src/su.c
++++ b/src/su.c
+@@ -499,6 +499,11 @@ static void check_perms_nopam (const struct passwd *pw)
+ /*@observer@*/const char *password = pw->pw_passwd;
+ RETSIGTYPE (*oldsig) (int);
+
++ if (strcmp (pw->pw_passwd, "") == 0) {
++ fprintf(stderr, _("Password field is empty, this is invalid.\n"));
++ exit(1);
++ }
++
+ if (caller_is_root) {
+ return;
+ }
+--
+2.26.3
+
diff --git a/patches/sys-apps/shadow/0002-su-login-Introduce-PREVENT_NO_AUTH.patch b/patches/sys-apps/shadow/0002-su-login-Introduce-PREVENT_NO_AUTH.patch
@@ -0,0 +1,104 @@
+From b52ef69b3b8442a77eeb18b7bf8f9b47148d6c34 Mon Sep 17 00:00:00 2001
+From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
+Date: Mon, 15 Mar 2021 10:25:50 +0100
+Subject: [PATCH 2/2] su & login: Introduce PREVENT_NO_AUTH
+
+---
+ etc/login.defs | 9 +++++++++
+ lib/getdef.c | 1 +
+ src/login.c | 13 +++++++++++--
+ src/su.c | 20 +++++++++++++++-----
+ 4 files changed, 36 insertions(+), 7 deletions(-)
+
+diff --git a/etc/login.defs b/etc/login.defs
+index a2f8cd50..f6b613a1 100644
+--- a/etc/login.defs
++++ b/etc/login.defs
+@@ -428,3 +428,12 @@ USERGROUPS_ENAB yes
+ # missing.
+ #
+ #FORCE_SHADOW yes
++
++#
++# Prevents an empty password field to be interpreted as "no authentication
++# required".
++# Set to "yes" to prevent for all accounts
++# Set to "superuser" to prevent for UID 0 / root (default)
++# Set to "no" to not prevent for any account (dangerous, historical default)
++
++PREVENT_NO_AUTH yes
+diff --git a/lib/getdef.c b/lib/getdef.c
+index 00f6abfe..d25d13f4 100644
+--- a/lib/getdef.c
++++ b/lib/getdef.c
+@@ -149,6 +149,7 @@ static struct itemdef def_table[] = {
+ {"USE_TCB", NULL},
+ #endif
+ {"FORCE_SHADOW", NULL},
++ {"PREVENT_NO_AUTH", NULL},
+ {NULL, NULL}
+ };
+
+diff --git a/src/login.c b/src/login.c
+index 0c0b5c86..be84a884 100644
+--- a/src/login.c
++++ b/src/login.c
+@@ -978,9 +978,18 @@ int main (int argc, char **argv)
+ || ('*' == user_passwd[0])) {
+ failed = true;
+ }
+- /* Treat empty password field as invalid */
++
+ if (strcmp (user_passwd, "") == 0) {
+- failed = true;
++ char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
++ if(prevent_no_auth == NULL) {
++ prevent_no_auth = "superuser";
++ }
++ if(strcmp(prevent_no_auth, "yes") == 0) {
++ failed = true;
++ } else if( (pwd->pw_uid == 0)
++ && (strcmp(prevent_no_auth, "superuser") == 0)) {
++ failed = true;
++ }
+ }
+ }
+
+diff --git a/src/su.c b/src/su.c
+index 638f533f..9cae4b2f 100644
+--- a/src/su.c
++++ b/src/su.c
+@@ -499,15 +499,25 @@ static void check_perms_nopam (const struct passwd *pw)
+ /*@observer@*/const char *password = pw->pw_passwd;
+ RETSIGTYPE (*oldsig) (int);
+
+- if (strcmp (pw->pw_passwd, "") == 0) {
+- fprintf(stderr, _("Password field is empty, this is invalid.\n"));
+- exit(1);
+- }
+-
+ if (caller_is_root) {
+ return;
+ }
+
++ if (strcmp (pw->pw_passwd, "") == 0) {
++ char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
++ if(prevent_no_auth == NULL) {
++ prevent_no_auth = "superuser";
++ }
++ if(strcmp(prevent_no_auth, "yes") == 0) {
++ fprintf(stderr, _("Password field is empty, this is forbidden for all accounts.\n"));
++ exit(1);
++ } else if( (pw->pw_uid == 0)
++ && (strcmp(prevent_no_auth, "superuser") == 0)) {
++ fprintf(stderr, _("Password field is empty, this is forbidden for super-user.\n"));
++ exit(1);
++ }
++ }
++
+ /*
+ * BSD systems only allow "wheel" to SU to root. USG systems don't,
+ * so we make this a configurable option.
+--
+2.26.3
+
diff --git a/patches/sys-apps/shadow/empty-passwd-assert.patch b/patches/sys-apps/shadow/empty-passwd-assert.patch
@@ -1,32 +0,0 @@
-From 1b1df50a8fb020e33b1dd2d3a6a7605a09a2a2be Mon Sep 17 00:00:00 2001
-From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
-Date: Sun, 14 Mar 2021 19:13:13 +0100
-Subject: [PATCH] su: Treat an empty passwd field as invalid
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Otherwise it's treated like the “require no password” clause while it probably
-should be treated like a normal su that can't validate anyway.
-
-A similar change should be done for USE_PAM.
----
- src/su.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/src/su.c b/src/su.c
-index cea3f155..b064d71b 100644
---- a/src/su.c
-+++ b/src/su.c
-@@ -501,6 +501,11 @@ static void check_perms_nopam (const struct passwd *pw)
- /*@observer@*/const char *password = pw->pw_passwd;
- RETSIGTYPE (*oldsig) (int);
-
-+ if (strcmp (pw->pw_passwd, "") == 0) {
-+ fprintf(stderr, _("Password field is empty, this is invalid.\n"));
-+ exit(1);
-+ }
-+
- if (caller_is_root) {
- return;
- }