X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=loginutils%2Fsulogin.c;h=77eff9f8dc415b0395a4474c59eb17f1d54484a8;hb=9f5a577a3241597cb5e7ba9f6df33c2e3c440e44;hp=36b10fbc4f05271fa17b99084ae4c198b986f10e;hpb=b6adbf1be29841501cc49917249e85f273e1df7c;p=oweals%2Fbusybox.git diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 36b10fbc4..77eff9f8d 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c @@ -5,76 +5,54 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include - #include "libbb.h" +#include -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) +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; const char *shell; #if ENABLE_FEATURE_SHADOWPASSWDS /* Using _r function to avoid pulling in static buffers */ char buffer[256]; struct spwd spw; - struct spwd *result; #endif logmode = LOGMODE_BOTH; openlog(applet_name, 0, LOG_AUTH); - if (getopt32(argc, argv, "t:", &timeout_arg)) { - timeout = xatoi_u(timeout_arg); - } + opt_complementary = "t+"; /* -t N */ + getopt32(argv, "t:", &timeout); + argv += optind; - if (argv[optind]) { + if (argv[0]) { close(0); close(1); - dup(xopen(argv[optind], O_RDWR)); + dup(xopen(argv[0], O_RDWR)); close(2); 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); pwd = getpwuid(0); if (!pwd) { @@ -82,15 +60,24 @@ int sulogin_main(int argc, char **argv) } #if ENABLE_FEATURE_SHADOWPASSWDS - if (getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result)) { - goto auth_error; + { + /* 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; } - pwd->pw_passwd = spw.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):"); @@ -98,29 +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()); shell = getenv("SUSHELL"); - if (!shell) shell = getenv("sushell"); + if (!shell) + shell = getenv("sushell"); if (!shell) { shell = "/bin/sh"; if (pwd->pw_shell[0]) shell = pwd->pw_shell; } - run_shell(shell, 1, 0, 0); - /* never returns */ + /* 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"); }