aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-04-13 12:57:04 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-04-13 12:57:04 +0200
commit335681ca8e39144fa19814f7ba10d0fe760e4055 (patch)
tree81c20a0be3daab564c842f510126037bf2331ab2
parent517a82c5b6b5e279f3e96a6774445a2952ca312b (diff)
downloadbusybox-w32-335681ca8e39144fa19814f7ba10d0fe760e4055.tar.gz
busybox-w32-335681ca8e39144fa19814f7ba10d0fe760e4055.tar.bz2
busybox-w32-335681ca8e39144fa19814f7ba10d0fe760e4055.zip
su: FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
When this feature is enabled, blank passwords are not accepted by su unless the user is on a secure TTY defined in /etc/securetty. This resembles the default PAM configuration of some Linux distros which specify the nullok_secure option for pam_unix.so. Based on patch by Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--include/libbb.h1
-rw-r--r--libbb/correct_password.c4
-rw-r--r--loginutils/su.c27
3 files changed, 25 insertions, 7 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 6b33ffad6..b889dd7d7 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1486,6 +1486,7 @@ int check_securetty(const char *short_tty) FAST_FUNC;
1486#else 1486#else
1487static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; } 1487static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; }
1488#endif 1488#endif
1489#define CHECKPASS_PW_HAS_EMPTY_PASSWORD 2
1489int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC; 1490int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC;
1490int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC; 1491int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC;
1491int ask_and_check_password(const struct passwd *pw) FAST_FUNC; 1492int ask_and_check_password(const struct passwd *pw) FAST_FUNC;
diff --git a/libbb/correct_password.c b/libbb/correct_password.c
index 513c93028..3436edc30 100644
--- a/libbb/correct_password.c
+++ b/libbb/correct_password.c
@@ -88,7 +88,7 @@ int FAST_FUNC check_password(const struct passwd *pw, const char *plaintext)
88 88
89 89
90/* Ask the user for a password. 90/* Ask the user for a password.
91 * Return 1 without asking if PW has an empty password. 91 * Return CHECKPASS_PW_HAS_EMPTY_PASSWORD without asking if PW has an empty password.
92 * Return -1 on EOF, error while reading input, or timeout. 92 * Return -1 on EOF, error while reading input, or timeout.
93 * Return 1 if the user gives the correct password for entry PW, 93 * Return 1 if the user gives the correct password for entry PW,
94 * 0 if not. 94 * 0 if not.
@@ -105,7 +105,7 @@ int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw,
105 105
106 pw_pass = get_passwd(pw, buffer); 106 pw_pass = get_passwd(pw, buffer);
107 if (!pw_pass[0]) /* empty password field? */ 107 if (!pw_pass[0]) /* empty password field? */
108 return 1; 108 return CHECKPASS_PW_HAS_EMPTY_PASSWORD;
109 109
110 plaintext = bb_ask(STDIN_FILENO, timeout, prompt); 110 plaintext = bb_ask(STDIN_FILENO, timeout, prompt);
111 if (!plaintext) { 111 if (!plaintext) {
diff --git a/loginutils/su.c b/loginutils/su.c
index d04b85fb1..f2cd799ae 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -23,6 +23,11 @@
23//config: bool "If user's shell is not in /etc/shells, disallow -s PROG" 23//config: bool "If user's shell is not in /etc/shells, disallow -s PROG"
24//config: default y 24//config: default y
25//config: depends on SU 25//config: depends on SU
26//config:
27//config:config FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
28//config: bool "Disallow blank passwords from TTYs other than specified in /etc/securetty"
29//config: default n
30//config: depends on SU
26 31
27//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */ 32//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
28//applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE)) 33//applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE))
@@ -79,6 +84,7 @@ int su_main(int argc UNUSED_PARAM, char **argv)
79 char user_buf[64]; 84 char user_buf[64];
80#endif 85#endif
81 const char *old_user; 86 const char *old_user;
87 int r;
82 88
83 /* Note: we don't use "'+': stop at first non-option" idiom here. 89 /* Note: we don't use "'+': stop at first non-option" idiom here.
84 * For su, "SCRIPT ARGS" or "-c CMD ARGS" do not stop option parsing: 90 * For su, "SCRIPT ARGS" or "-c CMD ARGS" do not stop option parsing:
@@ -99,6 +105,11 @@ int su_main(int argc UNUSED_PARAM, char **argv)
99 argv++; 105 argv++;
100 } 106 }
101 107
108 tty = xmalloc_ttyname(STDIN_FILENO);
109 if (!tty)
110 tty = "none";
111 tty = skip_dev_pfx(tty);
112
102 if (ENABLE_FEATURE_SU_SYSLOG) { 113 if (ENABLE_FEATURE_SU_SYSLOG) {
103 /* The utmp entry (via getlogin) is probably the best way to 114 /* The utmp entry (via getlogin) is probably the best way to
104 * identify the user, especially if someone su's from a su-shell. 115 * identify the user, especially if someone su's from a su-shell.
@@ -112,20 +123,26 @@ int su_main(int argc UNUSED_PARAM, char **argv)
112 pw = getpwuid(cur_uid); 123 pw = getpwuid(cur_uid);
113 old_user = pw ? xstrdup(pw->pw_name) : ""; 124 old_user = pw ? xstrdup(pw->pw_name) : "";
114 } 125 }
115 tty = xmalloc_ttyname(2);
116 if (!tty) {
117 tty = "none";
118 }
119 openlog(applet_name, 0, LOG_AUTH); 126 openlog(applet_name, 0, LOG_AUTH);
120 } 127 }
121 128
122 pw = xgetpwnam(opt_username); 129 pw = xgetpwnam(opt_username);
123 130
124 if (cur_uid == 0 || ask_and_check_password(pw) > 0) { 131 r = 1;
132 if (cur_uid != 0)
133 r = ask_and_check_password(pw);
134 if (r > 0) {
135 if (ENABLE_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
136 && r == CHECKPASS_PW_HAS_EMPTY_PASSWORD
137 && !check_securetty(tty)
138 ) {
139 goto fail;
140 }
125 if (ENABLE_FEATURE_SU_SYSLOG) 141 if (ENABLE_FEATURE_SU_SYSLOG)
126 syslog(LOG_NOTICE, "%c %s %s:%s", 142 syslog(LOG_NOTICE, "%c %s %s:%s",
127 '+', tty, old_user, opt_username); 143 '+', tty, old_user, opt_username);
128 } else { 144 } else {
145 fail:
129 if (ENABLE_FEATURE_SU_SYSLOG) 146 if (ENABLE_FEATURE_SU_SYSLOG)
130 syslog(LOG_NOTICE, "%c %s %s:%s", 147 syslog(LOG_NOTICE, "%c %s %s:%s",
131 '-', tty, old_user, opt_username); 148 '-', tty, old_user, opt_username);