From 9c1c605b1a8f34aef347bd9c2e4aea251e556d1b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 19 Nov 2013 13:09:06 +0100 Subject: [PATCH] sulogin: use common password-checking routine. This needed some extensions correct_passwd() function, which got renamed ask_and_check_password() to better describe what it does. function old new delta ask_and_check_password_extended - 215 +215 ask_and_check_password - 12 +12 vlock_main 394 397 +3 sulogin_main 494 326 -168 correct_password 207 - -207 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 1/1 up/down: 230/-375) Total: -145 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 3 ++- libbb/correct_password.c | 21 ++++++++++++++------ loginutils/login.c | 2 +- loginutils/su.c | 2 +- loginutils/sulogin.c | 43 ++++++---------------------------------- loginutils/vlock.c | 2 +- 6 files changed, 26 insertions(+), 47 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 58271655d..e99bb928f 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1301,7 +1301,8 @@ int sd_listen_fds(void); #define SETUP_ENV_TO_TMP (1 << 2) #define SETUP_ENV_NO_CHDIR (1 << 4) extern void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC; -extern int correct_password(const struct passwd *pw) FAST_FUNC; +extern int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC; +extern int ask_and_check_password(const struct passwd *pw) FAST_FUNC; /* Returns a malloced string */ #if !ENABLE_USE_BB_CRYPT #define pw_encrypt(clear, salt, cleanup) pw_encrypt(clear, salt) diff --git a/libbb/correct_password.c b/libbb/correct_password.c index 7cabd33d0..d02d0d6a0 100644 --- a/libbb/correct_password.c +++ b/libbb/correct_password.c @@ -31,12 +31,15 @@ #include "libbb.h" /* Ask the user for a password. + * Return 1 without asking if PW has an empty password. + * Return -1 on EOF, error while reading input, or timeout. * Return 1 if the user gives the correct password for entry PW, - * 0 if not. Return 1 without asking if PW has an empty password. + * 0 if not. * - * NULL pw means "just fake it for login with bad username" */ - -int FAST_FUNC correct_password(const struct passwd *pw) + * NULL pw means "just fake it for login with bad username" + */ +int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw, + int timeout, const char *prompt) { char *unencrypted, *encrypted; const char *correct; @@ -65,9 +68,10 @@ int FAST_FUNC correct_password(const struct passwd *pw) return 1; fake_it: - unencrypted = bb_ask_stdin("Password: "); + unencrypted = bb_ask(STDIN_FILENO, timeout, prompt); if (!unencrypted) { - return 0; + /* EOF (such as ^D) or error (such as ^C) */ + return -1; } encrypted = pw_encrypt(unencrypted, correct, 1); r = (strcmp(encrypted, correct) == 0); @@ -75,3 +79,8 @@ int FAST_FUNC correct_password(const struct passwd *pw) memset(unencrypted, 0, strlen(unencrypted)); return r; } + +int FAST_FUNC ask_and_check_password(const struct passwd *pw) +{ + return ask_and_check_password_extended(pw, 0, "Password: "); +} diff --git a/loginutils/login.c b/loginutils/login.c index 6ec8dc42e..a4b19ccfc 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -420,7 +420,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) * Note that reads (in no-echo mode) trash tty attributes. * If we get interrupted by SIGALRM, we need to restore attrs. */ - if (correct_password(pw)) + if (ask_and_check_password(pw) > 0) break; #endif /* ENABLE_PAM */ auth_failed: diff --git a/loginutils/su.c b/loginutils/su.c index 2ec05e125..c51f26f70 100644 --- a/loginutils/su.c +++ b/loginutils/su.c @@ -93,7 +93,7 @@ int su_main(int argc UNUSED_PARAM, char **argv) pw = xgetpwnam(opt_username); - if (cur_uid == 0 || correct_password(pw)) { + if (cur_uid == 0 || ask_and_check_password(pw) > 0) { if (ENABLE_FEATURE_SU_SYSLOG) syslog(LOG_NOTICE, "%c %s %s:%s", '+', tty, old_user, opt_username); diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 65e638489..2a2909937 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c @@ -14,24 +14,12 @@ #include "libbb.h" #include -//static void catchalarm(int UNUSED_PARAM junk) -//{ -// exit(EXIT_FAILURE); -//} - - int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int sulogin_main(int argc UNUSED_PARAM, char **argv) { - char *cp; int timeout = 0; 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); @@ -62,43 +50,24 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) 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) { - char *encrypted; int r; - /* cp points to a static buffer */ - cp = bb_ask(STDIN_FILENO, timeout, - "Give root password for system maintenance\n" - "(or type Control-D for normal startup):"); - if (!cp) { + r = ask_and_check_password_extended(pwd, timeout, + "Give root password for system maintenance\n" + "(or type Control-D for normal startup):" + ); + if (r < 0) { /* ^D, ^C, timeout, or read error */ bb_info_msg("Normal startup"); return 0; } - encrypted = pw_encrypt(cp, pwd->pw_passwd, 1); - r = strcmp(encrypted, pwd->pw_passwd); - free(encrypted); - if (r == 0) { + if (r > 0) { break; } bb_do_delay(LOGIN_FAIL_DELAY); bb_info_msg("Login incorrect"); } - memset(cp, 0, strlen(cp)); -// signal(SIGALRM, SIG_DFL); bb_info_msg("System Maintenance Mode"); diff --git a/loginutils/vlock.c b/loginutils/vlock.c index 75af9390e..44b14e6bc 100644 --- a/loginutils/vlock.c +++ b/loginutils/vlock.c @@ -104,7 +104,7 @@ int vlock_main(int argc UNUSED_PARAM, char **argv) /* "s" if -a, else "": */ "s" + !option_mask32, pw->pw_name ); - if (correct_password(pw)) { + if (ask_and_check_password(pw) > 0) { break; } bb_do_delay(LOGIN_FAIL_DELAY);