diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-26 16:18:37 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-26 16:18:37 +0000 |
commit | b6b00dd55e035bfbe311a527b567962ffa77ee43 (patch) | |
tree | cafc4d13785448e5a78bd40a51697ee07f07ac12 /src/sulogin.c | |
parent | Adding debian version 1:4.13+dfsg1-5. (diff) | |
download | shadow-b6b00dd55e035bfbe311a527b567962ffa77ee43.tar.xz shadow-b6b00dd55e035bfbe311a527b567962ffa77ee43.zip |
Merging upstream version 1:4.15.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/sulogin.c')
-rw-r--r-- | src/sulogin.c | 182 |
1 files changed, 81 insertions, 101 deletions
diff --git a/src/sulogin.c b/src/sulogin.c index 2c5e094..2097174 100644 --- a/src/sulogin.c +++ b/src/sulogin.c @@ -16,6 +16,11 @@ #include <signal.h> #include <stdio.h> #include <sys/ioctl.h> +#include <sys/types.h> + +#include "agetpass.h" +#include "alloc.h" +#include "attr.h" #include "defines.h" #include "getdef.h" #include "prototypes.h" @@ -24,113 +29,76 @@ #include "exitcodes.h" #include "shadowlog.h" + /* * Global variables */ -const char *Prog; - -static char name[BUFSIZ]; -static char pass[BUFSIZ]; +static const char Prog[] = "sulogin"; -static struct passwd pwent; extern char **newenvp; -extern size_t newenvc; - -extern char **environ; #ifndef ALARM #define ALARM 60 #endif -/* local function prototypes */ + static void catch_signals (int); +static int pw_entry(const char *name, struct passwd *pwent); -static void catch_signals (unused int sig) + +static void catch_signals (MAYBE_UNUSED int sig) { _exit (1); } -/* - * syslogd is usually not running at the time when sulogin is typically - * called, cluttering the screen with unnecessary messages. Suggested by - * Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm - */ -#undef USE_SYSLOG - /*ARGSUSED*/ int main (int argc, char **argv) +int +main(int argc, char *argv[]) { + int err = 0; + char **envp = environ; + TERMIO termio; + struct passwd pwent = {}; + bool done; #ifndef USE_PAM - const char *env; -#endif /* !USE_PAM */ - char **envp = environ; - TERMIO termio; - int err = 0; - -#ifdef USE_TERMIO - ioctl (0, TCGETA, &termio); - termio.c_iflag |= (ICRNL | IXON); - termio.c_oflag |= (OPOST | ONLCR); - termio.c_cflag |= (CREAD); - termio.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK); - ioctl (0, TCSETAF, &termio); + const char *env; #endif -#ifdef USE_TERMIOS + + tcgetattr (0, &termio); termio.c_iflag |= (ICRNL | IXON); termio.c_oflag |= (CREAD); termio.c_lflag |= (ECHO | ECHOE | ECHOK | ICANON | ISIG); tcsetattr (0, TCSANOW, &termio); -#endif - Prog = Basename (argv[0]); log_set_progname(Prog); log_set_logfd(stderr); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); -#ifdef USE_SYSLOG - OPENLOG ("sulogin"); -#endif - initenv (); + initenv(); if (argc > 1) { - close (0); - close (1); - close (2); - - if (open (argv[1], O_RDWR) >= 0) { - dup (0); - dup (0); - } else { -#ifdef USE_SYSLOG - SYSLOG (LOG_WARN, "cannot open %s\n", argv[1]); - closelog (); -#endif - exit (1); - } + close(0); + close(1); + close(2); + + if (open(argv[1], O_RDWR) == -1) + exit(1); + dup(0); + dup(0); } if (access (PASSWD_FILE, F_OK) == -1) { /* must be a password file! */ (void) puts (_("No password file")); -#ifdef USE_SYSLOG - SYSLOG (LOG_WARN, "No password file\n"); - closelog (); -#endif exit (1); } #if !defined(DEBUG) && defined(SULOGIN_ONLY_INIT) if (getppid () != 1) { /* parent must be INIT */ -#ifdef USE_SYSLOG - SYSLOG (LOG_WARN, "Pid == %d, not 1\n", getppid ()); - closelog (); -#endif exit (1); } #endif if ((isatty (0) == 0) || (isatty (1) == 0) || (isatty (2) == 0)) { -#ifdef USE_SYSLOG - closelog (); -#endif exit (1); /* must be a terminal */ } /* If we were init, we need to start a new session */ @@ -156,24 +124,17 @@ static void catch_signals (unused int sig) } #endif /* !USE_PAM */ - (void) strcpy (name, "root"); /* KLUDGE!!! */ - (void) signal (SIGALRM, catch_signals); /* exit if the timer expires */ (void) alarm (ALARM); /* only wait so long ... */ - while (true) { /* repeatedly get login/password pairs */ - char *cp; - pw_entry (name, &pwent); /* get entry from password file */ - if (pwent.pw_name == (char *) 0) { + do { /* repeatedly get login/password pairs */ + char *pass; + if (pw_entry("root", &pwent) == -1) { /* get entry from password file */ /* * Fail secure */ - (void) puts (_("No password entry for 'root'")); -#ifdef USE_SYSLOG - SYSLOG (LOG_WARN, "No password entry for 'root'\n"); - closelog (); -#endif - exit (1); + (void) puts(_("No password entry for 'root'")); + exit(1); } /* @@ -182,7 +143,7 @@ static void catch_signals (unused int sig) */ /* get a password for root */ - cp = getpass (_( + pass = agetpass (_( "\n" "Type control-d to proceed with normal startup,\n" "(or give root password for system maintenance):")); @@ -192,46 +153,65 @@ static void catch_signals (unused int sig) * it will work with standard getpass() (no NULL on EOF). * --marekm */ - if ((NULL == cp) || ('\0' == *cp)) { -#ifdef USE_SYSLOG - SYSLOG (LOG_INFO, "Normal startup\n"); - closelog (); -#endif + if ((NULL == pass) || ('\0' == *pass)) { + erase_pass (pass); (void) puts (""); #ifdef TELINIT - execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) 0); + execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) NULL); #endif exit (0); - } else { - STRFCPY (pass, cp); - strzero (cp); - } - if (valid (pass, &pwent)) { /* check encrypted passwords ... */ - break; /* ... encrypted passwords matched */ } -#ifdef USE_SYSLOG - SYSLOG (LOG_WARN, "Incorrect root password\n"); -#endif - sleep (2); - (void) puts (_("Login incorrect")); - } - memzero (pass, sizeof pass); + done = valid(pass, &pwent); + erase_pass (pass); + + if (!done) { /* check encrypted passwords ... */ + /* ... encrypted passwords did not match */ + sleep (2); + (void) puts (_("Login incorrect")); + } + } while (!done); (void) alarm (0); (void) signal (SIGALRM, SIG_DFL); environ = newenvp; /* make new environment active */ (void) puts (_("Entering System Maintenance Mode")); -#ifdef USE_SYSLOG - SYSLOG (LOG_INFO, "System Maintenance Mode\n"); -#endif -#ifdef USE_SYSLOG - closelog (); -#endif /* exec the shell finally. */ - err = shell (pwent.pw_shell, (char *) 0, environ); + err = shell (pwent.pw_shell, NULL, environ); return ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); } + +static int +pw_entry(const char *name, struct passwd *pwent) +{ + struct spwd *spwd; + struct passwd *passwd; + + if (!(passwd = getpwnam(name))) /* local, no need for xgetpwnam */ + return -1; + + free(pwent->pw_name); + pwent->pw_name = xstrdup(passwd->pw_name); + pwent->pw_uid = passwd->pw_uid; + pwent->pw_gid = passwd->pw_gid; + free(pwent->pw_gecos); + pwent->pw_gecos = xstrdup(passwd->pw_gecos); + free(pwent->pw_dir); + pwent->pw_dir = xstrdup(passwd->pw_dir); + free(pwent->pw_shell); + pwent->pw_shell = xstrdup(passwd->pw_shell); +#if !defined(AUTOSHADOW) + /* local, no need for xgetspnam */ + if ((spwd = getspnam(name))) { + free(pwent->pw_passwd); + pwent->pw_passwd = xstrdup(spwd->sp_pwdp); + return 0; + } +#endif + free(pwent->pw_passwd); + pwent->pw_passwd = xstrdup(passwd->pw_passwd); + return 0; +} |