X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=loginutils%2Fsulogin.c;h=77eff9f8dc415b0395a4474c59eb17f1d54484a8;hb=9f5a577a3241597cb5e7ba9f6df33c2e3c440e44;hp=fef3760e99dbaebdd9cc7868a1b21f44ba9114c8;hpb=9852d5a1e65d23dece9bdfa2483409dda258748f;p=oweals%2Fbusybox.git diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index fef3760e9..77eff9f8d 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c @@ -5,86 +5,79 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ +#include "libbb.h" #include -#include "busybox.h" - -static const char * const 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 ATTRIBUTE_UNUSED junk) -{ - exit(EXIT_FAILURE); -} +//static void catchalarm(int UNUSED_PARAM junk) +//{ +// exit(EXIT_FAILURE); +//} -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; int timeout = 0; - char *timeout_arg; - const char * const *p; struct passwd *pwd; - struct spwd *spwd; + 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(bb_applet_name, 0, LOG_AUTH); + openlog(applet_name, 0, LOG_AUTH); - if (bb_getopt_ulflags (argc, argv, "t:", &timeout_arg)) { - if (safe_strtoi(timeout_arg, &timeout)) { - timeout = 0; - } - } + opt_complementary = "t+"; /* -t N */ + getopt32(argv, "t:", &timeout); + argv += optind; - if (argv[optind]) { + if (argv[0]) { close(0); close(1); + dup(xopen(argv[0], O_RDWR)); close(2); - dup(xopen(argv[optind], O_RDWR)); dup(0); } + /* Malicious use like "sulogin /dev/sda"? */ if (!isatty(0) || !isatty(1) || !isatty(2)) { logmode = LOGMODE_SYSLOG; bb_error_msg_and_die("not a tty"); } - /* Clear out anything dangerous from the environment */ - for (p = forbid; *p; p++) - unsetenv(*p); + /* Clear dangerous stuff, set PATH */ + sanitize_env_if_suid(); - signal(SIGALRM, catchalarm); +// bb_ask() already handles this +// signal(SIGALRM, catchalarm); - if (!(pwd = getpwuid(0))) { + pwd = getpwuid(0); + if (!pwd) { goto auth_error; - } + } - if (ENABLE_FEATURE_SHADOWPASSWDS) { - if (!(spwd = getspnam(pwd->pw_name))) { +#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 = spwd->sp_pwdp; + pwd->pw_passwd = result->sp_pwdp; } +#endif while (1) { + char *encrypted; + int r; + /* cp points to a static buffer that is zeroed every time */ - cp = bb_askpass(timeout, + cp = bb_ask(STDIN_FILENO, timeout, "Give root password for system maintenance\n" "(or type Control-D for normal startup):"); @@ -92,22 +85,33 @@ int sulogin_main(int argc, char **argv) bb_info_msg("Normal startup"); return 0; } - if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) { + encrypted = pw_encrypt(cp, pwd->pw_passwd, 1); + r = strcmp(encrypted, pwd->pw_passwd); + free(encrypted); + if (r == 0) { break; } bb_do_delay(FAIL_DELAY); bb_error_msg("login incorrect"); } memset(cp, 0, strlen(cp)); - signal(SIGALRM, SIG_DFL); +// signal(SIGALRM, SIG_DFL); bb_info_msg("System Maintenance Mode"); - USE_SELINUX(renew_current_security_context()); + IF_SELINUX(renew_current_security_context()); - run_shell(pwd->pw_shell, 1, 0, 0); - /* never returns */ + 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'"); + auth_error: + bb_error_msg_and_die("no password entry for root"); }