Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | /* vi: set sw=4 ts=4: */ /* * Mini sulogin implementation for busybox * * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ #include <syslog.h> #include "libbb.h" static const char forbid[] ALIGN1 = "ENV" "\0" "BASH_ENV" "\0" "HOME" "\0" "IFS" "\0" "PATH" "\0" "SHELL" "\0" "LD_LIBRARY_PATH" "\0" "LD_PRELOAD" "\0" "LD_TRACE_LOADED_OBJECTS" "\0" "LD_BIND_NOW" "\0" "LD_AOUT_LIBRARY_PATH" "\0" "LD_AOUT_PRELOAD" "\0" "LD_NOWARN" "\0" "LD_KEEPDIR" "\0"; //static void catchalarm(int ATTRIBUTE_UNUSED junk) //{ // exit(EXIT_FAILURE); //} int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int sulogin_main(int argc, char **argv) { char *cp; int timeout = 0; char *timeout_arg; const char *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; #endif logmode = LOGMODE_BOTH; openlog(applet_name, 0, LOG_AUTH); if (getopt32(argv, "t:", &timeout_arg)) { timeout = xatoi_u(timeout_arg); } if (argv[optind]) { close(0); close(1); dup(xopen(argv[optind], O_RDWR)); close(2); dup(0); } 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 */ p = forbid; do { unsetenv(p); p += strlen(p) + 1; } while (*p); // bb_askpass() already handles this // signal(SIGALRM, catchalarm); pwd = getpwuid(0); if (!pwd) { goto auth_error; } #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 while (1) { /* cp points to a static buffer that is zeroed every time */ cp = bb_askpass(timeout, "Give root password for system maintenance\n" "(or type Control-D for normal startup):"); if (!cp || !*cp) { bb_info_msg("Normal startup"); return 0; } if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) { break; } bb_do_delay(FAIL_DELAY); bb_error_msg("login incorrect"); } 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"); } |