From 4aca87515a5083ae0e31ce3177189fd43b6d05ac Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 3 Jan 2015 13:58:15 +0100 Subject: patch to Vanilla Tomato 1.28 --- release/src/router/busybox/loginutils/sulogin.c | 253 +++++++++--------------- 1 file changed, 93 insertions(+), 160 deletions(-) (limited to 'release/src/router/busybox/loginutils/sulogin.c') diff --git a/release/src/router/busybox/loginutils/sulogin.c b/release/src/router/busybox/loginutils/sulogin.c index bb4716e0..4ffefe93 100644 --- a/release/src/router/busybox/loginutils/sulogin.c +++ b/release/src/router/busybox/loginutils/sulogin.c @@ -1,184 +1,117 @@ /* vi: set sw=4 ts=4: */ -#include -#include -#include -#include -#include +/* + * Mini sulogin implementation for busybox + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ + +#include "libbb.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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); -} +//static void catchalarm(int UNUSED_PARAM junk) +//{ +// exit(EXIT_FAILURE); +//} -extern int sulogin_main(int argc, char **argv) + +int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int sulogin_main(int argc UNUSED_PARAM, 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(bb_path_passwd_file, 0) == -1) { - syslog(LOG_WARNING, "No password file\n"); - bb_error_msg_and_die("No password file\n"); + const char *shell; +#if ENABLE_FEATURE_SHADOWPASSWDS + /* Using _r function to avoid pulling in static buffers */ + char buffer[256]; + struct spwd spw; +#endif + + logmode = LOGMODE_BOTH; + openlog(applet_name, 0, LOG_AUTH); + + opt_complementary = "t+"; /* -t N */ + getopt32(argv, "t:", &timeout); + argv += optind; + + if (argv[0]) { + close(0); + close(1); + dup(xopen(argv[0], O_RDWR)); + close(2); + dup(0); } + + /* Malicious use like "sulogin /dev/sda"? */ if (!isatty(0) || !isatty(1) || !isatty(2)) { - exit(EXIT_FAILURE); + logmode = LOGMODE_SYSLOG; + bb_error_msg_and_die("not a tty"); } + /* Clear dangerous stuff, set PATH */ + sanitize_env_if_suid(); - /* Clear out anything dangerous from the environment */ - for (p = forbid; *p; p++) - unsetenv(*p); +// bb_ask() already handles this +// signal(SIGALRM, catchalarm); - - signal(SIGALRM, catchalarm); - alarm(timeout); - if (!(pwd = getpwnam(name))) { - syslog(LOG_WARNING, "No password entry for `root'\n"); - bb_error_msg_and_die("No password entry for `root'\n"); + pwd = getpwuid(0); + if (!pwd) { + goto auth_error; } - 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; + +#if ENABLE_FEATURE_SHADOWPASSWDS + { + /* getspnam_r may return 0 yet set result to NULL. + * At least glibc 2.4 does this. Be extra paranoid here. */ + struct spwd *result = NULL; + int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result); + if (r || !result) { + goto auth_error; } + pwd->pw_passwd = result->sp_pwdp; } -#endif /* CONFIG_FEATURE_SHADOWPASSWDS */ +#endif + while (1) { - cp = getpass(SULOGIN_PROMPT); + char *encrypted; + int r; + + /* cp points to a static buffer that is zeroed every time */ + cp = bb_ask(STDIN_FILENO, timeout, + "Give root password for system maintenance\n" + "(or type Control-D for normal startup):"); + 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)); + bb_info_msg("Normal startup"); + return 0; } - if (strcmp(pw_encrypt(pass, pwent.pw_passwd), pwent.pw_passwd) == 0) { + encrypted = pw_encrypt(cp, pwd->pw_passwd, 1); + r = strcmp(encrypted, pwd->pw_passwd); + free(encrypted); + if (r == 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"); + bb_do_delay(FAIL_DELAY); + bb_error_msg("login incorrect"); } - 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); + memset(cp, 0, strlen(cp)); +// signal(SIGALRM, SIG_DFL); + + bb_info_msg("System Maintenance Mode"); + + USE_SELINUX(renew_current_security_context()); + + shell = getenv("SUSHELL"); + if (!shell) + shell = getenv("sushell"); + if (!shell) { + shell = "/bin/sh"; + if (pwd->pw_shell[0]) + shell = pwd->pw_shell; + } + /* Exec login shell with no additional parameters. Never returns. */ + run_shell(shell, 1, NULL, NULL); + + auth_error: + bb_error_msg_and_die("no password entry for root"); } -- cgit v1.2.3-54-g00ecf