4 * This program gives Linux machines a reasonable secure way to boot single
5 * user. It forces the user to supply the root password before a shell is
6 * started. If there is a shadow password file and the encrypted root password
7 * is "x" the shadow password will be used.
9 * Copyright (C) 1998-2003 Miquel van Smoorenburg.
10 * Copyright (C) 2012 Karel Zak <kzak@redhat.com>
11 * Copyright (C) 2012 Werner Fink <werner@suse.de>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <sys/types.h>
42 #include <sys/ioctl.h>
47 #ifdef HAVE_LIBSELINUX
48 # include <selinux/selinux.h>
49 # include <selinux/get_context_list.h>
53 #include "closestream.h"
55 #include "pathnames.h"
65 static unsigned int timeout
;
67 static volatile uint32_t openfd
; /* Remember higher file descriptors */
68 static volatile uint32_t *usemask
;
70 struct sigaction saved_sigint
;
71 struct sigaction saved_sigtstp
;
72 struct sigaction saved_sigquit
;
73 struct sigaction saved_sighup
;
74 struct sigaction saved_sigchld
;
76 static volatile sig_atomic_t alarm_rised
;
77 static volatile sig_atomic_t sigchild
;
84 * Fix the tty modes and set reasonable defaults.
86 static void tcinit(struct console
*con
)
88 int mode
= 0, flags
= 0;
89 struct termios
*tio
= &con
->tio
;
94 if (tcgetattr(fd
, tio
) < 0) {
95 warn(_("tcgetattr failed"));
96 con
->flags
|= CON_NOTTY
;
100 /* Handle serial lines here */
101 if (ioctl(fd
, TIOCMGET
, (char *) &mode
) == 0) {
102 speed_t ispeed
, ospeed
;
105 /* this is a modem line */
106 con
->flags
|= CON_SERIAL
;
108 /* Flush input and output queues on modem lines */
109 tcflush(fd
, TCIOFLUSH
);
111 ispeed
= cfgetispeed(tio
);
112 ospeed
= cfgetospeed(tio
);
114 if (!ispeed
) ispeed
= TTYDEF_SPEED
;
115 if (!ospeed
) ospeed
= TTYDEF_SPEED
;
117 tio
->c_cflag
= CREAD
| CS8
| HUPCL
| (tio
->c_cflag
& CLOCAL
);
120 tio
->c_oflag
&= OPOST
| ONLCR
;
122 cfsetispeed(tio
, ispeed
);
123 cfsetospeed(tio
, ospeed
);
126 tio
->c_cc
[VTIME
] = 0;
129 if (ioctl(fd
, TIOCGWINSZ
, &ws
) == 0) {
131 if (ws
.ws_row
== 0) {
135 if (ws
.ws_col
== 0) {
140 ignore_result( ioctl(fd
, TIOCSWINSZ
, &ws
) );
143 setlocale(LC_CTYPE
, "POSIX");
146 #if defined(IUTF8) && defined(KDGKBMODE)
147 /* Detect mode of current keyboard setup, e.g. for UTF-8 */
148 if (ioctl(fd
, KDGKBMODE
, &mode
) < 0)
152 setlocale(LC_CTYPE
, "C.UTF-8");
153 flags
|= UL_TTY_UTF8
;
159 setlocale(LC_CTYPE
, "POSIX");
163 setlocale(LC_CTYPE
, "POSIX");
165 reset_virtual_console(tio
, flags
);
167 if (tcsetattr(fd
, TCSANOW
, tio
))
168 warn(_("tcsetattr failed"));
170 /* Enable blocking mode for read and write */
171 if ((flags
= fcntl(fd
, F_GETFL
, 0)) != -1)
172 ignore_result( fcntl(fd
, F_SETFL
, flags
& ~O_NONBLOCK
) );
176 * Finalize the tty modes on modem lines.
178 static void tcfinal(struct console
*con
)
183 if ((con
->flags
& CON_SERIAL
) == 0) {
184 setenv("TERM", "linux", 1);
187 if (con
->flags
& CON_NOTTY
)
190 setenv("TERM", "vt102", 1);
194 tio
->c_iflag
|= (IXON
| IXOFF
);
195 tio
->c_lflag
|= (ICANON
| ISIG
| ECHO
|ECHOE
|ECHOK
|ECHOKE
);
196 tio
->c_oflag
|= OPOST
;
198 tio
->c_cc
[VINTR
] = CINTR
;
199 tio
->c_cc
[VQUIT
] = CQUIT
;
200 tio
->c_cc
[VERASE
] = con
->cp
.erase
;
201 tio
->c_cc
[VKILL
] = con
->cp
.kill
;
202 tio
->c_cc
[VEOF
] = CEOF
;
204 tio
->c_cc
[VSWTC
] = _POSIX_VDISABLE
;
206 tio
->c_cc
[VSWTCH
] = _POSIX_VDISABLE
;
208 tio
->c_cc
[VSTART
] = CSTART
;
209 tio
->c_cc
[VSTOP
] = CSTOP
;
210 tio
->c_cc
[VSUSP
] = CSUSP
;
211 tio
->c_cc
[VEOL
] = _POSIX_VDISABLE
;
213 if (con
->cp
.eol
== CR
) {
214 tio
->c_iflag
|= ICRNL
;
215 tio
->c_iflag
&= ~(INLCR
|IGNCR
);
216 tio
->c_oflag
|= ONLCR
;
217 tio
->c_oflag
&= ~(OCRNL
|ONLRET
);
220 switch (con
->cp
.parity
) {
223 tio
->c_cflag
&= ~(PARODD
| PARENB
);
224 tio
->c_iflag
&= ~(INPCK
| ISTRIP
);
226 case 1: /* odd parity */
227 tio
->c_cflag
|= PARODD
;
229 case 2: /* even parity */
230 tio
->c_cflag
|= PARENB
;
231 tio
->c_iflag
|= (INPCK
| ISTRIP
);
233 case (1 | 2): /* no parity bit */
234 tio
->c_cflag
&= ~CSIZE
;
239 /* Set line attributes */
240 tcsetattr(fd
, TCSANOW
, tio
);
246 static void alrm_handler(int sig
__attribute__((unused
)))
248 /* Timeout expired */
252 static void chld_handler(int sig
__attribute__((unused
)))
257 static void mask_signal(int signal
, void (*handler
)(int),
258 struct sigaction
*origaction
)
260 struct sigaction newaction
;
262 newaction
.sa_handler
= handler
;
263 sigemptyset(&newaction
.sa_mask
);
264 newaction
.sa_flags
= 0;
266 sigaction(signal
, &newaction
, origaction
);
269 static void unmask_signal(int signal
, struct sigaction
*sa
)
271 sigaction(signal
, sa
, NULL
);
275 * See if an encrypted password is valid. The encrypted password is checked for
276 * traditional-style DES and FreeBSD-style MD5 encryption.
278 static int valid(const char *pass
)
291 * up to 4 bytes for the signature e.g. $1$
293 for (s
= pass
+1; *s
&& *s
!= '$'; s
++);
298 if ((off
= (off_t
)(s
-pass
)) > 4 || off
< 3)
301 memset(id
, '\0', sizeof(id
));
302 strncpy(id
, pass
, off
);
305 * up to 16 bytes for the salt
307 for (; *s
&& *s
!= '$'; s
++);
312 if ((off_t
)(s
-pass
) > 16)
318 * the MD5 hash (128 bits or 16 bytes) encoded in base64 = 22 bytes
320 if ((strcmp(id
, "$1$") == 0) && (len
< 22 || len
> 24))
324 * the SHA-256 hash 43 bytes
326 if ((strcmp(id
, "$5$") == 0) && (len
< 42 || len
> 44))
330 * the SHA-512 hash 86 bytes
332 if ((strcmp(id
, "$6$") == 0) && (len
< 85 || len
> 87))
340 if (strlen(pass
) != 13)
343 for (s
= pass
; *s
; s
++) {
344 if ((*s
< '0' || *s
> '9') &&
345 (*s
< 'a' || *s
> 'z') &&
346 (*s
< 'A' || *s
> 'Z') &&
347 *s
!= '.' && *s
!= '/')
354 * Set a variable if the value is not NULL.
356 static inline void set(char **var
, char *val
)
363 * Get the root password entry.
365 static struct passwd
*getrootpwent(int try_manually
)
367 static struct passwd pwd
;
371 static char line
[256];
372 static char sline
[256];
376 * First, we try to get the password the standard way using normal
379 if ((pw
= getpwnam("root")) &&
380 !strcmp(pw
->pw_passwd
, "x") &&
381 (spw
= getspnam("root")))
382 pw
->pw_passwd
= spw
->sp_pwdp
;
384 if (pw
|| !try_manually
)
388 * If we come here, we could not retrieve the root password through
389 * library calls and we try to read the password and shadow files
392 pwd
.pw_name
= "root";
394 pwd
.pw_gecos
= "Super User";
400 if ((fp
= fopen(_PATH_PASSWD
, "r")) == NULL
) {
401 warn(_("cannot open %s"), _PATH_PASSWD
);
406 * Find root in the password file.
408 while ((p
= fgets(line
, 256, fp
)) != NULL
) {
409 if (strncmp(line
, "root:", 5) != 0)
412 set(&pwd
.pw_passwd
, strsep(&p
, ":"));
415 set(&pwd
.pw_gecos
, strsep(&p
, ":"));
416 set(&pwd
.pw_dir
, strsep(&p
, ":"));
417 set(&pwd
.pw_shell
, strsep(&p
, "\n"));
425 * If the encrypted password is valid or not found, return.
428 warnx(_("%s: no entry for root\n"), _PATH_PASSWD
);
431 if (valid(pwd
.pw_passwd
))
435 * The password is invalid. If there is a shadow password, try it.
437 strcpy(pwd
.pw_passwd
, "");
438 if ((fp
= fopen(_PATH_SHADOW_PASSWD
, "r")) == NULL
) {
439 warn(_("cannot open %s"), _PATH_PASSWD
);
442 while ((p
= fgets(sline
, 256, fp
)) != NULL
) {
443 if (strncmp(sline
, "root:", 5) != 0)
446 set(&pwd
.pw_passwd
, strsep(&p
, ":"));
452 * If the password is still invalid, NULL it, and return.
455 warnx(_("%s: no entry for root"), _PATH_SHADOW_PASSWD
);
456 strcpy(pwd
.pw_passwd
, "");
458 if (!valid(pwd
.pw_passwd
)) {
459 warnx(_("%s: root password garbled"), _PATH_SHADOW_PASSWD
);
460 strcpy(pwd
.pw_passwd
, "");
466 * Ask by prompt for the password.
468 static void doprompt(const char *crypted
, struct console
*con
)
472 if (con
->flags
& CON_SERIAL
) {
475 * For prompting: map NL in output to CR-NL
476 * otherwise we may see stairs in the output.
478 tty
.c_oflag
|= (ONLCR
| OPOST
);
479 tcsetattr(con
->fd
, TCSADRAIN
, &tty
);
481 if (con
->file
== (FILE*)0) {
482 if ((con
->file
= fdopen(con
->fd
, "r+")) == (FILE*)0)
485 #if defined(USE_ONELINE)
487 fprintf(con
->file
, _("Give root password for login: "));
489 fprintf(con
->file
, _("Press enter for login: "));
492 fprintf(con
->file
, _("Give root password for maintenance\n"));
494 fprintf(con
->file
, _("Press enter for maintenance"));
495 fprintf(con
->file
, _("(or type Control-D to continue): "));
499 if (con
->flags
& CON_SERIAL
)
500 tcsetattr(con
->fd
, TCSADRAIN
, &con
->tio
);
504 * Make sure to have an own session and controlling terminal
506 static void setup(struct console
*con
)
508 pid_t pid
, pgrp
, ppgrp
, ttypgrp
;
511 if (con
->flags
& CON_NOTTY
)
516 * Only go through this trouble if the new
517 * tty doesn't fall in this process group.
521 ppgrp
= getpgid(getppid());
522 ttypgrp
= tcgetpgrp(fd
);
524 if (pgrp
!= ttypgrp
&& ppgrp
!= ttypgrp
) {
525 if (pid
!= getsid(0)) {
526 if (pid
== getpgid(0))
527 setpgid(0, getpgid(getppid()));
531 mask_signal(SIGHUP
, SIG_IGN
, &saved_sighup
);
533 ioctl(STDIN_FILENO
, TIOCNOTTY
, (char *)1);
534 unmask_signal(SIGHUP
, &saved_sighup
);
535 if (fd
> STDIN_FILENO
) close(STDIN_FILENO
);
536 if (fd
> STDOUT_FILENO
) close(STDOUT_FILENO
);
537 if (fd
> STDERR_FILENO
) close(STDERR_FILENO
);
539 ioctl(fd
, TIOCSCTTY
, (char *)1);
540 tcsetpgrp(fd
, ppgrp
);
542 dup2(fd
, STDIN_FILENO
);
543 dup2(fd
, STDOUT_FILENO
);
544 dup2(fd
, STDERR_FILENO
);
545 con
->fd
= STDIN_FILENO
;
547 for (fd
= STDERR_FILENO
+1; fd
< 32; fd
++) {
548 if (openfd
& (1<<fd
)) {
556 * Ask for the password. Note that there is no default timeout as we normally
557 * skip this during boot.
559 static char *getpasswd(struct console
*con
)
563 static char pass
[128], *ptr
;
571 if (con
->flags
& CON_NOTTY
)
577 tty
.c_iflag
&= ~(IUCLC
|IXON
|IXOFF
|IXANY
);
578 tty
.c_lflag
&= ~(ECHO
|ECHOE
|ECHOK
|ECHONL
|TOSTOP
|ISIG
);
579 tc
= (tcsetattr(fd
, TCSAFLUSH
, &tty
) == 0);
581 sa
.sa_handler
= alrm_handler
;
583 sigaction(SIGALRM
, &sa
, NULL
);
589 cp
->eol
= *ptr
= '\0';
591 eightbit
= ((con
->flags
& CON_SERIAL
) == 0 || (tty
.c_cflag
& (PARODD
|PARENB
)) == 0);
592 while (cp
->eol
== '\0') {
593 if (read(fd
, &c
, 1) < 1) {
594 if (errno
== EINTR
|| errno
== EAGAIN
) {
607 fprintf(stderr
, "sulogin: read(%s): %m\n\r", con
->tty
);
615 else if (c
!= (ascval
= (c
& 0177))) {
617 for (bits
= 1, mask
= 1; mask
& 0177; mask
<<= 1) {
621 cp
->parity
|= ((bits
& 1) ? 1 : 2);
641 while (ptr
> &pass
[0])
647 if ((size_t)(ptr
- &pass
[0]) >= (sizeof(pass
) -1 )) {
648 fprintf(stderr
, "sulogin: input overrun at %s\n\r", con
->tty
);
659 tcsetattr(fd
, TCSAFLUSH
, &con
->tio
);
660 if (ret
&& *ret
!= '\0')
668 * Password was OK, execute a shell.
670 static void sushell(struct passwd
*pwd
)
672 char shell
[PATH_MAX
];
678 * Set directory and shell.
680 if (chdir(pwd
->pw_dir
) != 0) {
681 warn(_("%s: change directory failed"), pwd
->pw_dir
);
682 printf(_("Logging in with home = \"/\".\n"));
685 warn(_("change directory to system root failed"));
688 if ((p
= getenv("SUSHELL")) != NULL
)
690 else if ((p
= getenv("sushell")) != NULL
)
693 if (pwd
->pw_shell
[0])
694 su_shell
= pwd
->pw_shell
;
696 su_shell
= "/bin/sh";
698 if ((p
= strrchr(su_shell
, '/')) == NULL
)
703 snprintf(shell
, sizeof(shell
), profile
? "-%s" : "%s", p
);
706 * Set some important environment variables.
708 if (getcwd(home
, sizeof(home
)) == NULL
)
711 setenv("HOME", home
, 1);
712 setenv("LOGNAME", "root", 1);
713 setenv("USER", "root", 1);
715 setenv("SHLVL","0",1);
718 * Try to execute a shell.
720 setenv("SHELL", su_shell
, 1);
721 unmask_signal(SIGINT
, &saved_sigint
);
722 unmask_signal(SIGTSTP
, &saved_sigtstp
);
723 unmask_signal(SIGQUIT
, &saved_sigquit
);
724 mask_signal(SIGHUP
, SIG_DFL
, NULL
);
726 #ifdef HAVE_LIBSELINUX
727 if (is_selinux_enabled() > 0) {
728 security_context_t scon
=NULL
;
731 if (getseuserbyname("root", &seuser
, &level
) == 0) {
732 if (get_default_context_with_level(seuser
, level
, 0, &scon
) == 0) {
733 if (setexeccon(scon
) != 0)
734 warnx(_("setexeccon failed"));
742 execl(su_shell
, shell
, NULL
);
743 warn(_("%s: exec failed"), su_shell
);
745 setenv("SHELL", "/bin/sh", 1);
746 execl("/bin/sh", profile
? "-sh" : "sh", NULL
);
747 warn(_("%s: exec failed"), "/bin/sh");
750 static void usage(FILE *out
)
752 fputs(USAGE_HEADER
, out
);
754 " %s [options] [tty device]\n"), program_invocation_short_name
);
756 fputs(USAGE_OPTIONS
, out
);
757 fputs(_(" -p, --login-shell start a login shell\n"
758 " -t, --timeout <seconds> max time to wait for a password (default: no limit)\n"
759 " -e, --force examine password files directly if getpwnam(3) fails\n"),
762 fputs(USAGE_SEPARATOR
, out
);
763 fputs(USAGE_HELP
, out
);
764 fputs(USAGE_VERSION
, out
);
765 fprintf(out
, USAGE_MAN_TAIL("sulogin(8)"));
768 int main(int argc
, char **argv
)
771 struct list_head
*ptr
;
780 static const struct option longopts
[] = {
781 { "login-shell", 0, 0, 'p' },
782 { "timeout", 1, 0, 't' },
783 { "force", 0, 0, 'e' },
784 { "help", 0, 0, 'h' },
785 { "version", 0, 0, 'V' },
790 * If we are init we need to set up a own session.
792 if ((pid
= getpid()) == 1) {
794 ignore_result( ioctl(STDIN_FILENO
, TIOCSCTTY
, (char *) 1) );
797 setlocale(LC_ALL
, "");
798 bindtextdomain(PACKAGE
, LOCALEDIR
);
800 atexit(close_stdout
); /* XXX */
803 * See if we have a timeout flag.
805 while ((c
= getopt_long(argc
, argv
, "ehpt:V", longopts
, NULL
)) != -1) {
808 timeout
= strtou32_or_err(optarg
, _("invalid timeout argument"));
817 printf(UTIL_LINUX_VERSION
);
830 errx(EXIT_FAILURE
, _("only root can run this program."));
832 mask_signal(SIGQUIT
, SIG_IGN
, &saved_sigquit
);
833 mask_signal(SIGTSTP
, SIG_IGN
, &saved_sigtstp
);
834 mask_signal(SIGINT
, SIG_IGN
, &saved_sigint
);
835 mask_signal(SIGHUP
, SIG_IGN
, &saved_sighup
);
838 * See if we need to open an other tty device.
843 if (!tty
|| *tty
== '\0')
844 tty
= getenv("CONSOLE");
847 * Detect possible consoles, use stdin as fallback.
848 * If an optional tty is given, reconnect it to stdin.
850 reconnect
= detect_consoles(tty
, STDIN_FILENO
, &consoles
);
853 * If previous stdin was not the speified tty and therefore reconnected
854 * to the specified tty also reconnect stdout and stderr.
857 if (isatty(STDOUT_FILENO
) == 0)
858 dup2(STDOUT_FILENO
, STDIN_FILENO
);
859 if (isatty(STDERR_FILENO
) == 0)
860 dup2(STDOUT_FILENO
, STDERR_FILENO
);
866 if (list_empty(&consoles
)) {
869 errx(EXIT_FAILURE
, _("cannot open console: %m\n"));
873 * Get the root password.
875 if ((pwd
= getrootpwent(opt_e
)) == NULL
) {
876 warnx(_("cannot open password database."));
881 * Ask for the password on the consoles.
883 list_for_each(ptr
, &consoles
) {
884 con
= list_entry(ptr
, struct console
, entry
);
885 if (con
->id
>= CONMAX
)
888 openfd
|= (1 << con
->fd
);
892 if ((con
->fd
= open(con
->tty
, O_RDWR
| O_NOCTTY
| O_NONBLOCK
)) < 0)
894 openfd
|= (1 << con
->fd
);
897 ptr
= (&consoles
)->next
;
898 usemask
= (uint32_t*) mmap(NULL
, sizeof(uint32_t),
899 PROT_READ
|PROT_WRITE
,
900 MAP_ANONYMOUS
|MAP_SHARED
, -1, 0);
902 if (ptr
->next
== &consoles
) {
903 con
= list_entry(ptr
, struct console
, entry
);
907 mask_signal(SIGCHLD
, chld_handler
, &saved_sigchld
);
909 con
= list_entry(ptr
, struct console
, entry
);
910 if (con
->id
>= CONMAX
)
913 switch ((con
->pid
= fork())) {
915 mask_signal(SIGCHLD
, SIG_DFL
, NULL
);
920 const char *passwd
= pwd
->pw_passwd
;
922 int failed
= 0, doshell
= 0;
924 doprompt(passwd
, con
);
925 if ((answer
= getpasswd(con
)) == NULL
)
928 if (passwd
[0] == '\0')
931 const char *cryptbuf
;
932 cryptbuf
= crypt(answer
, passwd
);
933 if (cryptbuf
== NULL
)
934 warnx(_("crypt failed: %m\n"));
935 else if (strcmp(cryptbuf
, pwd
->pw_passwd
) == 0)
940 *usemask
|= (1<<con
->id
);
942 *usemask
&= ~(1<<con
->id
);
946 mask_signal(SIGQUIT
, SIG_IGN
, &saved_sigquit
);
947 mask_signal(SIGTSTP
, SIG_IGN
, &saved_sigtstp
);
948 mask_signal(SIGINT
, SIG_IGN
, &saved_sigint
);
951 fprintf(stderr
, _("Can not execute su shell\n\n"));
954 fprintf(stderr
, _("Login incorrect\n\n"));
958 warnx(_("Timed out\n\n"));
961 * User pressed Control-D.
965 warnx(_("Can not fork: %m\n"));
973 } while (ptr
!= &consoles
);
975 while ((pid
= wait(&status
))) {
980 list_for_each(ptr
, &consoles
) {
981 con
= list_entry(ptr
, struct console
, entry
);
982 if (con
->pid
== pid
) {
983 *usemask
&= ~(1<<con
->id
);
986 if (kill(con
->pid
, 0) < 0) {
987 *usemask
&= ~(1<<con
->id
);
990 if (*usemask
& (1<<con
->id
))
992 kill(con
->pid
, SIGHUP
);
994 kill(con
->pid
, SIGKILL
);
998 mask_signal(SIGCHLD
, SIG_DFL
, NULL
);