diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-13 12:57:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-13 12:57:04 +0200 |
commit | 335681ca8e39144fa19814f7ba10d0fe760e4055 (patch) | |
tree | 81c20a0be3daab564c842f510126037bf2331ab2 | |
parent | 517a82c5b6b5e279f3e96a6774445a2952ca312b (diff) | |
download | busybox-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.h | 1 | ||||
-rw-r--r-- | libbb/correct_password.c | 4 | ||||
-rw-r--r-- | loginutils/su.c | 27 |
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 |
1487 | static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; } | 1487 | static 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 | ||
1489 | int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC; | 1490 | int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC; |
1490 | int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC; | 1491 | int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC; |
1491 | int ask_and_check_password(const struct passwd *pw) FAST_FUNC; | 1492 | int 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); |