summaryrefslogtreecommitdiffhomepage
path: root/loginutils/sulogin.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-06-23 04:24:25 +0000
committerEric Andersen <andersen@codepoet.org>2002-06-23 04:24:25 +0000
commit27f64e1f4eb4354844f6553e37501deffde8373e (patch)
tree632fbb26b13ad67f6efa335c33a22551b2707930 /loginutils/sulogin.c
parent0fbff134f400ea51540cfd6ef5eeaeab60f9a5de (diff)
Port over the last of the tinylogin applets
-Erik
Diffstat (limited to 'loginutils/sulogin.c')
-rw-r--r--loginutils/sulogin.c184
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);
+}