dcavalca / rpms / util-linux

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