summaryrefslogtreecommitdiff
path: root/loginutils/passwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'loginutils/passwd.c')
-rw-r--r--loginutils/passwd.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
index 99afde2..0842b71 100644
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -93,11 +93,9 @@ int passwd_main(int argc, char **argv)
uid_t myuid;
struct rlimit rlimit_fsize;
char c;
-
#if ENABLE_FEATURE_SHADOWPASSWDS
/* Using _r function to avoid pulling in static buffers */
struct spwd spw;
- struct spwd *result;
char buffer[256];
#endif
@@ -128,16 +126,19 @@ int passwd_main(int argc, char **argv)
}
#if ENABLE_FEATURE_SHADOWPASSWDS
- /* getspnam_r() can lie! Even if user isn't in shadow, it can
- * return success (pwd field was seen set to "!" in this case) */
- if (getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result)
- || LONE_CHAR(spw.sp_pwdp, '!')) {
- /* LOGMODE_BOTH */
- bb_error_msg("no record of %s in %s, using %s",
- name, bb_path_shadow_file,
- bb_path_passwd_file);
- } else {
- pw->pw_passwd = spw.sp_pwdp;
+ {
+ /* 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;
+ if (getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result)
+ || !result || strcmp(result->sp_namp, pw->pw_name) != 0) {
+ /* LOGMODE_BOTH */
+ bb_error_msg("no record of %s in %s, using %s",
+ name, bb_path_shadow_file,
+ bb_path_passwd_file);
+ } else {
+ pw->pw_passwd = result->sp_pwdp;
+ }
}
#endif
@@ -161,7 +162,7 @@ int passwd_main(int argc, char **argv)
newp = xasprintf("!%s", pw->pw_passwd);
} else if (opt & OPT_unlock) {
if (c) goto skip; /* not '!' */
- /* pw->pw_passwd pints to static storage,
+ /* pw->pw_passwd points to static storage,
* strdup'ing to avoid nasty surprizes */
newp = xstrdup(&pw->pw_passwd[1]);
} else if (opt & OPT_delete) {