diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-06-23 04:24:25 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-06-23 04:24:25 +0000 |
commit | 27f64e1f4eb4354844f6553e37501deffde8373e (patch) | |
tree | 632fbb26b13ad67f6efa335c33a22551b2707930 /loginutils/sulogin.c | |
parent | 0fbff134f400ea51540cfd6ef5eeaeab60f9a5de (diff) |
Port over the last of the tinylogin applets
-Erik
Diffstat (limited to 'loginutils/sulogin.c')
-rw-r--r-- | loginutils/sulogin.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c new file mode 100644 index 000000000..a654ffb89 --- /dev/null +++ b/loginutils/sulogin.c @@ -0,0 +1,184 @@ +/* vi: set sw=4 ts=4: */ +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <termios.h> +#include <unistd.h> +#include <utmp.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <ctype.h> +#include <time.h> + +#include "busybox.h" + + +// sulogin defines +#define SULOGIN_PROMPT "\nGive root password for system maintenance\n" \ + "(or type Control-D for normal startup):" + +static const char *forbid[] = { + "ENV", + "BASH_ENV", + "HOME", + "IFS", + "PATH", + "SHELL", + "LD_LIBRARY_PATH", + "LD_PRELOAD", + "LD_TRACE_LOADED_OBJECTS", + "LD_BIND_NOW", + "LD_AOUT_LIBRARY_PATH", + "LD_AOUT_PRELOAD", + "LD_NOWARN", + "LD_KEEPDIR", + (char *) 0 +}; + + + +static void catchalarm(int junk) +{ + exit(EXIT_FAILURE); +} + + +extern int sulogin_main(int argc, char **argv) +{ + char *cp; + char *device = (char *) 0; + const char *name = "root"; + int timeout = 0; + static char pass[BUFSIZ]; + struct termios termio; + struct passwd pwent; + struct passwd *pwd; + time_t start, now; + const char **p; +#ifdef CONFIG_FEATURE_SHADOWPASSWDS + struct spwd *spwd = NULL; +#endif /* CONFIG_FEATURE_SHADOWPASSWDS */ + + tcgetattr(0, &termio); + /* set control chars */ + termio.c_cc[VINTR] = 3; /* C-c */ + termio.c_cc[VQUIT] = 28; /* C-\ */ + termio.c_cc[VERASE] = 127; /* C-? */ + termio.c_cc[VKILL] = 21; /* C-u */ + termio.c_cc[VEOF] = 4; /* C-d */ + termio.c_cc[VSTART] = 17; /* C-q */ + termio.c_cc[VSTOP] = 19; /* C-s */ + termio.c_cc[VSUSP] = 26; /* C-z */ + /* use line dicipline 0 */ + termio.c_line = 0; + /* Make it be sane */ + termio.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; + termio.c_cflag |= CREAD|HUPCL|CLOCAL; + /* input modes */ + termio.c_iflag = ICRNL | IXON | IXOFF; + /* output modes */ + termio.c_oflag = OPOST | ONLCR; + /* local modes */ + termio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; + tcsetattr(0, TCSANOW, &termio); + openlog("sulogin", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH); + if (argc > 1) { + if (strncmp(argv[1], "-t", 2) == 0) { + if (strcmp(argv[1], "-t") == 0) { + if (argc > 2) { + timeout = atoi(argv[2]); + if (argc > 3) { + device = argv[3]; + } + } + } else { + if (argc > 2) { + device = argv[2]; + } + } + } else { + device = argv[1]; + } + if (device) { + close(0); + close(1); + close(2); + if (open(device, O_RDWR) >= 0) { + dup(0); + dup(0); + } else { + syslog(LOG_WARNING, "cannot open %s\n", device); + exit(EXIT_FAILURE); + } + } + } + if (access(passwd_file, 0) == -1) { + syslog(LOG_WARNING, "No password file\n"); + error_msg_and_die("No password file\n"); + } + if (!isatty(0) || !isatty(1) || !isatty(2)) { + exit(EXIT_FAILURE); + } + + + /* Clear out anything dangerous from the environment */ + for (p = forbid; *p; p++) + unsetenv(*p); + + + signal(SIGALRM, catchalarm); + alarm(timeout); + if (!(pwd = getpwnam(name))) { + syslog(LOG_WARNING, "No password entry for `root'\n"); + error_msg_and_die("No password entry for `root'\n"); + } + pwent = *pwd; +#ifdef CONFIG_FEATURE_SHADOWPASSWDS + spwd = NULL; + if (pwd && ((strcmp(pwd->pw_passwd, "x") == 0) + || (strcmp(pwd->pw_passwd, "*") == 0))) { + endspent(); + spwd = getspnam(name); + if (spwd) { + pwent.pw_passwd = spwd->sp_pwdp; + } + } +#endif /* CONFIG_FEATURE_SHADOWPASSWDS */ + while (1) { + cp = getpass(SULOGIN_PROMPT); + if (!cp || !*cp) { + puts("\n"); + fflush(stdout); + syslog(LOG_INFO, "Normal startup\n"); + exit(EXIT_SUCCESS); + } else { + safe_strncpy(pass, cp, sizeof(pass)); + bzero(cp, strlen(cp)); + } + if (strcmp(pw_encrypt(pass, pwent.pw_passwd), pwent.pw_passwd) == 0) { + break; + } + time(&start); + now = start; + while (difftime(now, start) < FAIL_DELAY) { + sleep(FAIL_DELAY); + time(&now); + } + puts("Login incorrect"); + fflush(stdout); + syslog(LOG_WARNING, "Incorrect root password\n"); + } + bzero(pass, strlen(pass)); + alarm(0); + signal(SIGALRM, SIG_DFL); + puts("Entering System Maintenance Mode\n"); + fflush(stdout); + syslog(LOG_INFO, "System Maintenance Mode\n"); + run_shell(pwent.pw_shell, 1, 0, 0); + return (0); +} |