cdown / rpms / util-linux

Forked from rpms/util-linux 2 years ago
Clone
ad9577
From a08c1a6aadaa27e4070fe58242d55464d6c7a3e7 Mon Sep 17 00:00:00 2001
ad9577
From: Karel Zak <kzak@redhat.com>
ad9577
Date: Mon, 25 May 2015 15:30:52 +0200
ad9577
Subject: [PATCH 164/173] sulogin: improve support for locked root account
ad9577
ad9577
Some installations and distributions don't use a root account password
ad9577
for security reasons and use sudo instead. In that case, asking for the
ad9577
password makes no sense, and it is not even considered as valid as it's just
ad9577
"*" or "!".
ad9577
ad9577
In these cases --force is required to just start a root shell and no
ad9577
ask for password.
ad9577
ad9577
I don't think it's a good idea to automatically start root shell when
ad9577
locked account is detected. It's possible that the machine is on
ad9577
public place and for example Ubuntu uses root account disabled by
ad9577
default (and also Fedora when installed by yum/dnf without anaconda).
ad9577
ad9577
The --force option forces admins to think about it...
ad9577
ad9577
The distro maintainers can also use --force in their initscripts or
ad9577
systemd emergency.service if they believe that promiscuous setting is
ad9577
the right thing for the distro.
ad9577
ad9577
Addresses: https://bugs.debian.org/326678
ad9577
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1561200
ad9577
Upstream: http://github.com/karelzak/util-linux/commit/7ff1162e67164cb4ece19dd809c26272461aa254
ad9577
Signed-off-by: Karel Zak <kzak@redhat.com>
ad9577
---
ad9577
 login-utils/sulogin.8 | 13 +++++++++----
ad9577
 login-utils/sulogin.c | 48 ++++++++++++++++++++++++++++++++++--------------
ad9577
 2 files changed, 43 insertions(+), 18 deletions(-)
ad9577
ad9577
diff --git a/login-utils/sulogin.8 b/login-utils/sulogin.8
ad9577
index b9dec165c..702487985 100644
ad9577
--- a/login-utils/sulogin.8
ad9577
+++ b/login-utils/sulogin.8
ad9577
@@ -35,8 +35,10 @@ Give root password for system maintenance
ad9577
 .br
ad9577
 (or type Control\-D for normal startup):
ad9577
 .PP
ad9577
-.I sulogin
ad9577
-will be connected to the current terminal, or to the optional tty device that
ad9577
+If the root account is locked and --force is specified, no password is required.
ad9577
+.PP
ad9577
+.B sulogin
ad9577
+will be connected to the current terminal, or to the optional \fItty\fR device that
ad9577
 can be specified on the command line (typically
ad9577
 .BR /dev/console ).
ad9577
 .PP
ad9577
@@ -50,8 +52,11 @@ from the system fails, manually examine
ad9577
 .I /etc/passwd
ad9577
 and
ad9577
 .I /etc/shadow
ad9577
-to get the password.  If they are damaged or nonexistent, sulogin will start
ad9577
-a root shell without asking for a password.
ad9577
+to get the password.  If these files are damaged or nonexistent, or when
ad9577
+root account is locked by '!' or '*' at the begin of the password then
ad9577
+.B sulogin
ad9577
+will \fBstart a root shell without asking for a password\fP.
ad9577
+.PP
ad9577
 .IP
ad9577
 Only use the
ad9577
 .B \-e
ad9577
diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
ad9577
index 6d03bc5ae..a17b91d71 100644
ad9577
--- a/login-utils/sulogin.c
ad9577
+++ b/login-utils/sulogin.c
ad9577
@@ -81,6 +81,13 @@ static volatile sig_atomic_t sigchild;
ad9577
 # define IUCLC		0
ad9577
 #endif
ad9577
 
ad9577
+static int locked_account_password(const char *passwd)
ad9577
+{
ad9577
+	if (passwd && (*passwd == '*' || *passwd == '!'))
ad9577
+		return 1;
ad9577
+	return 0;
ad9577
+}
ad9577
+
ad9577
 /*
ad9577
  * Fix the tty modes and set reasonable defaults.
ad9577
  */
ad9577
@@ -423,7 +430,6 @@ static struct passwd *getrootpwent(int try_manually)
ad9577
 		p = line;
ad9577
 		break;
ad9577
 	}
ad9577
-
ad9577
 	fclose(fp);
ad9577
 
ad9577
 	/*
ad9577
@@ -460,7 +466,8 @@ static struct passwd *getrootpwent(int try_manually)
ad9577
 		warnx(_("%s: no entry for root"), _PATH_SHADOW_PASSWD);
ad9577
 		*pwd.pw_passwd = '\0';
ad9577
 	}
ad9577
-	if (!valid(pwd.pw_passwd)) {
ad9577
+	/* locked accont passwords are valid too */
ad9577
+	if (!locked_account_password(pwd.pw_passwd) && !valid(pwd.pw_passwd)) {
ad9577
 		warnx(_("%s: root password garbled"), _PATH_SHADOW_PASSWD);
ad9577
 		*pwd.pw_passwd = '\0';
ad9577
 	}
ad9577
@@ -470,7 +477,7 @@ static struct passwd *getrootpwent(int try_manually)
ad9577
 /*
ad9577
  * Ask by prompt for the password.
ad9577
  */
ad9577
-static void doprompt(const char *crypted, struct console *con)
ad9577
+static void doprompt(const char *crypted, struct console *con, int deny)
ad9577
 {
ad9577
 	struct termios tty;
ad9577
 
ad9577
@@ -487,18 +494,25 @@ static void doprompt(const char *crypted, struct console *con)
ad9577
 		if  ((con->file = fdopen(con->fd, "r+")) == (FILE*)0)
ad9577
 			goto err;
ad9577
 	}
ad9577
+
ad9577
+	if (deny)
ad9577
+		fprintf(con->file, _("\nCannot open access to console, the root account is locked.\n"
ad9577
+				     "See sulogin(8) man page for more details.\n\n"
ad9577
+				     "Press Enter to continue.\n"));
ad9577
+	else {
ad9577
 #if defined(USE_ONELINE)
ad9577
-	if (crypted[0])
ad9577
-		fprintf(con->file, _("Give root password for login: "));
ad9577
-	else
ad9577
-		fprintf(con->file, _("Press enter for login: "));
ad9577
+		if (crypted[0] && !locked_account_password(crypted))
ad9577
+			fprintf(con->file, _("Give root password for login: "));
ad9577
+		else
ad9577
+			fprintf(con->file, _("Press Enter for login: "));
ad9577
 #else
ad9577
-	if (crypted[0])
ad9577
-		fprintf(con->file, _("Give root password for maintenance\n"));
ad9577
-	else
ad9577
-		fprintf(con->file, _("Press enter for maintenance"));
ad9577
-	fprintf(con->file, _("(or type Control-D to continue): "));
ad9577
+		if (crypted[0] && !locked_account_password(crypted))
ad9577
+			fprintf(con->file, _("Give root password for maintenance\n"));
ad9577
+		else
ad9577
+			fprintf(con->file, _("Press Enter for maintenance\n"));
ad9577
+		fprintf(con->file, _("(or press Control-D to continue): "));
ad9577
 #endif
ad9577
+	}
ad9577
 	fflush(con->file);
ad9577
 err:
ad9577
 	if (con->flags & CON_SERIAL)
ad9577
@@ -914,6 +928,7 @@ int main(int argc, char **argv)
ad9577
 		goto nofork;
ad9577
 	}
ad9577
 
ad9577
+
ad9577
 	mask_signal(SIGCHLD, chld_handler, &saved_sigchld);
ad9577
 	do {
ad9577
 		con = list_entry(ptr, struct console, entry);
ad9577
@@ -930,12 +945,17 @@ int main(int argc, char **argv)
ad9577
 				const char *passwd = pwd->pw_passwd;
ad9577
 				const char *answer;
ad9577
 				int failed = 0, doshell = 0;
ad9577
+				int deny = !opt_e && locked_account_password(pwd->pw_passwd);
ad9577
+
ad9577
+				doprompt(passwd, con, deny);
ad9577
 
ad9577
-				doprompt(passwd, con);
ad9577
 				if ((answer = getpasswd(con)) == NULL)
ad9577
 					break;
ad9577
+				if (deny)
ad9577
+					exit(EXIT_FAILURE);
ad9577
 
ad9577
-				if (passwd[0] == '\0')
ad9577
+				/* no password or locked account */
ad9577
+				if (!passwd[0] || locked_account_password(passwd))
ad9577
 					doshell++;
ad9577
 				else {
ad9577
 					const char *cryptbuf;
ad9577
-- 
ad9577
2.14.4
ad9577