[git commit] su: FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY

Denys Vlasenko vda.linux at googlemail.com
Thu Apr 13 10:57:04 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=335681ca8e39144fa19814f7ba10d0fe760e4055
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

When this feature is enabled, blank passwords are not accepted by su
unless the user is on a secure TTY defined in /etc/securetty. This
resembles the default PAM configuration of some Linux distros which
specify the nullok_secure option for pam_unix.so.

Based on patch by Kaarle Ritvanen <kaarle.ritvanen at datakunkku.fi>

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 include/libbb.h          |  1 +
 libbb/correct_password.c |  4 ++--
 loginutils/su.c          | 27 ++++++++++++++++++++++-----
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/include/libbb.h b/include/libbb.h
index 6b33ffa..b889dd7 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1486,6 +1486,7 @@ int check_securetty(const char *short_tty) FAST_FUNC;
 #else
 static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; }
 #endif
+#define CHECKPASS_PW_HAS_EMPTY_PASSWORD 2
 int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC;
 int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC;
 int ask_and_check_password(const struct passwd *pw) FAST_FUNC;
diff --git a/libbb/correct_password.c b/libbb/correct_password.c
index 513c930..3436edc 100644
--- a/libbb/correct_password.c
+++ b/libbb/correct_password.c
@@ -88,7 +88,7 @@ int FAST_FUNC check_password(const struct passwd *pw, const char *plaintext)
 
 
 /* Ask the user for a password.
- * Return 1 without asking if PW has an empty password.
+ * Return CHECKPASS_PW_HAS_EMPTY_PASSWORD without asking if PW has an empty password.
  * Return -1 on EOF, error while reading input, or timeout.
  * Return 1 if the user gives the correct password for entry PW,
  * 0 if not.
@@ -105,7 +105,7 @@ int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw,
 
 	pw_pass = get_passwd(pw, buffer);
 	if (!pw_pass[0]) /* empty password field? */
-		return 1;
+		return CHECKPASS_PW_HAS_EMPTY_PASSWORD;
 
 	plaintext = bb_ask(STDIN_FILENO, timeout, prompt);
 	if (!plaintext) {
diff --git a/loginutils/su.c b/loginutils/su.c
index d04b85f..f2cd799 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -23,6 +23,11 @@
 //config:	bool "If user's shell is not in /etc/shells, disallow -s PROG"
 //config:	default y
 //config:	depends on SU
+//config:
+//config:config FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
+//config:	bool "Disallow blank passwords from TTYs other than specified in /etc/securetty"
+//config:	default n
+//config:	depends on SU
 
 //applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
 //applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE))
@@ -79,6 +84,7 @@ int su_main(int argc UNUSED_PARAM, char **argv)
 	char user_buf[64];
 #endif
 	const char *old_user;
+	int r;
 
 	/* Note: we don't use "'+': stop at first non-option" idiom here.
 	 * For su, "SCRIPT ARGS" or "-c CMD ARGS" do not stop option parsing:
@@ -99,6 +105,11 @@ int su_main(int argc UNUSED_PARAM, char **argv)
 		argv++;
 	}
 
+	tty = xmalloc_ttyname(STDIN_FILENO);
+	if (!tty)
+		tty = "none";
+	tty = skip_dev_pfx(tty);
+
 	if (ENABLE_FEATURE_SU_SYSLOG) {
 		/* The utmp entry (via getlogin) is probably the best way to
 		 * identify the user, especially if someone su's from a su-shell.
@@ -112,20 +123,26 @@ int su_main(int argc UNUSED_PARAM, char **argv)
 			pw = getpwuid(cur_uid);
 			old_user = pw ? xstrdup(pw->pw_name) : "";
 		}
-		tty = xmalloc_ttyname(2);
-		if (!tty) {
-			tty = "none";
-		}
 		openlog(applet_name, 0, LOG_AUTH);
 	}
 
 	pw = xgetpwnam(opt_username);
 
-	if (cur_uid == 0 || ask_and_check_password(pw) > 0) {
+	r = 1;
+	if (cur_uid != 0)
+		r = ask_and_check_password(pw);
+	if (r > 0) {
+		if (ENABLE_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
+		 && r == CHECKPASS_PW_HAS_EMPTY_PASSWORD
+		 && !check_securetty(tty)
+		) {
+			goto fail;
+		}
 		if (ENABLE_FEATURE_SU_SYSLOG)
 			syslog(LOG_NOTICE, "%c %s %s:%s",
 				'+', tty, old_user, opt_username);
 	} else {
+ fail:
 		if (ENABLE_FEATURE_SU_SYSLOG)
 			syslog(LOG_NOTICE, "%c %s %s:%s",
 				'-', tty, old_user, opt_username);


More information about the busybox-cvs mailing list