Skip to content

Commit 7ff1162

Browse files
committed
sulogin: improve support for locked root account
Some installations and distributions don't use a root account password for security reasons and use sudo instead. In that case, asking for the password makes no sense, and it is not even considered as valid as it's just "*" or "!". In these cases --force is required to just start a root shell and no ask for password. I don't think it's a good idea to automatically start root shell when locked account is detected. It's possible that the machine is on public place and for example Ubuntu uses root account disabled by default (and also Fedora when installed by yum/dnf without anaconda). The --force option forces admins to think about it... The distro maintainers can also use --force in their initscripts or systemd emergency.service if they believe that promiscuous setting is the right thing for the distro. Addresses: https://bugs.debian.org/326678 Signed-off-by: Karel Zak <[email protected]>
1 parent 13c551f commit 7ff1162

File tree

2 files changed

+40
-16
lines changed

2 files changed

+40
-16
lines changed

login-utils/sulogin.8

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ Give root password for system maintenance
3333
.br
3434
(or type Control\-D for normal startup):
3535
.PP
36+
If the root account is locked and --force is specified, no password is required.
37+
.PP
3638
.B sulogin
3739
will be connected to the current terminal, or to the optional \fItty\fR device that
3840
can be specified on the command line (typically
@@ -48,9 +50,11 @@ fails, then examine
4850
.I /etc/passwd
4951
and
5052
.I /etc/shadow
51-
to get the password. If these files are damaged or nonexistent,
53+
to get the password. If these files are damaged or nonexistent, or when
54+
root account is locked by '!' or '*' at the begin of the password then
5255
.B sulogin
53-
will start a root shell without asking for a password.
56+
will \fBstart a root shell without asking for a password\fP.
57+
.PP
5458
.IP
5559
Only use the
5660
.B \-e

login-utils/sulogin.c

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ static volatile sig_atomic_t sigchild;
8181
# define IUCLC 0
8282
#endif
8383

84+
static int locked_account_password(const char *passwd)
85+
{
86+
if (passwd && (*passwd == '*' || *passwd == '!'))
87+
return 1;
88+
return 0;
89+
}
90+
8491
#ifdef TIOCGLCKTRMIOS
8592
/*
8693
* For the case plymouth is found on this system
@@ -485,7 +492,6 @@ static struct passwd *getrootpwent(int try_manually)
485492
p = line;
486493
break;
487494
}
488-
489495
fclose(fp);
490496

491497
/*
@@ -522,7 +528,8 @@ static struct passwd *getrootpwent(int try_manually)
522528
warnx(_("%s: no entry for root"), _PATH_SHADOW_PASSWD);
523529
*pwd.pw_passwd = '\0';
524530
}
525-
if (!valid(pwd.pw_passwd)) {
531+
/* locked accont passwords are valid too */
532+
if (!locked_account_password(pwd.pw_passwd) && !valid(pwd.pw_passwd)) {
526533
warnx(_("%s: root password garbled"), _PATH_SHADOW_PASSWD);
527534
*pwd.pw_passwd = '\0';
528535
}
@@ -532,7 +539,7 @@ static struct passwd *getrootpwent(int try_manually)
532539
/*
533540
* Ask by prompt for the password.
534541
*/
535-
static void doprompt(const char *crypted, struct console *con)
542+
static void doprompt(const char *crypted, struct console *con, int deny)
536543
{
537544
struct termios tty;
538545

@@ -549,18 +556,25 @@ static void doprompt(const char *crypted, struct console *con)
549556
if ((con->file = fdopen(con->fd, "r+")) == (FILE*)0)
550557
goto err;
551558
}
559+
560+
if (deny)
561+
fprintf(con->file, _("\nCannot open access to console, the root account is locked.\n"
562+
"See sulogin(8) man page for more details.\n\n"
563+
"Press Enter to continue.\n"));
564+
else {
552565
#if defined(USE_ONELINE)
553-
if (crypted[0])
554-
fprintf(con->file, _("Give root password for login: "));
555-
else
556-
fprintf(con->file, _("Press Enter for login: "));
566+
if (crypted[0] && !locked_account_password(crypted))
567+
fprintf(con->file, _("Give root password for login: "));
568+
else
569+
fprintf(con->file, _("Press Enter for login: "));
557570
#else
558-
if (crypted[0])
559-
fprintf(con->file, _("Give root password for maintenance\n"));
560-
else
561-
fprintf(con->file, _("Press Enter for maintenance"));
562-
fprintf(con->file, _("(or press Control-D to continue): "));
571+
if (crypted[0] && !locked_account_password(crypted))
572+
fprintf(con->file, _("Give root password for maintenance\n"));
573+
else
574+
fprintf(con->file, _("Press Enter for maintenance\n"));
575+
fprintf(con->file, _("(or press Control-D to continue): "));
563576
#endif
577+
}
564578
fflush(con->file);
565579
err:
566580
if (con->flags & CON_SERIAL)
@@ -980,6 +994,7 @@ int main(int argc, char **argv)
980994
goto nofork;
981995
}
982996

997+
983998
mask_signal(SIGCHLD, chld_handler, &saved_sigchld);
984999
do {
9851000
con = list_entry(ptr, struct console, entry);
@@ -996,12 +1011,17 @@ int main(int argc, char **argv)
9961011
const char *passwd = pwd->pw_passwd;
9971012
const char *answer;
9981013
int failed = 0, doshell = 0;
1014+
int deny = !opt_e && locked_account_password(pwd->pw_passwd);
1015+
1016+
doprompt(passwd, con, deny);
9991017

1000-
doprompt(passwd, con);
10011018
if ((answer = getpasswd(con)) == NULL)
10021019
break;
1020+
if (deny)
1021+
exit(EXIT_FAILURE);
10031022

1004-
if (passwd[0] == '\0')
1023+
/* no password or locked account */
1024+
if (!passwd[0] || locked_account_password(passwd))
10051025
doshell++;
10061026
else {
10071027
const char *cryptbuf;

0 commit comments

Comments
 (0)