From 20eb4585a140a4bcd7901d4892a3222ff9f0d122 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 2 Nov 2023 04:10:51 -0500 Subject: [PATCH] Wean su.c off shadow.h (so ndk can build it). --- lib/lib.h | 1 + lib/password.c | 27 +++++++++++++++++++++++++++ toys/lsb/su.c | 29 ++++++++++++++--------------- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/lib/lib.h b/lib/lib.h index bc4ff962..0a0bb7fb 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -359,6 +359,7 @@ char *unescape_url(char *str, int do_cut); // password.c int get_salt(char *salt, char *algo, int rand); int read_password(char *buff, int buflen, char *mesg); +char **get_userline(char *filename, char *username); int update_password(char *filename, char *username, char *entry, int pos); // commas.c diff --git a/lib/password.c b/lib/password.c index c1891aab..f653e41d 100644 --- a/lib/password.c +++ b/lib/password.c @@ -82,6 +82,33 @@ int read_password(char *buf, int buflen, char *mesg) return ret; } +// Read array of colon separated strings from file with given first entry +char **get_userline(char *filename, char *username) +{ + FILE *fp = xfopen(filename, "r"); + int len = strlen(username); + char *line = 0, **data; + size_t n = 0; + + while (getline(&line, &n, fp)) { + if (!strncmp(line, username, len) && line[len]==':') { + data = xzalloc(10*sizeof(char *)); + for (len = 0; len<9; len++) { + data[len] = line; + if (!(line = strchr(line, ':'))) break; + *line++ = 0; + } + return data; + } + memset(line, 0, strlen(line)); + free(line); + line = 0; + n = 0; + } + + return 0; +} + // update colon-separated text files ala /etc/{passwd,shadow,group,gshadow} // returns 1 for success, 0 for failure diff --git a/toys/lsb/su.c b/toys/lsb/su.c index 71df8a6b..78717221 100644 --- a/toys/lsb/su.c +++ b/toys/lsb/su.c @@ -37,13 +37,12 @@ config SU #include "toys.h" GLOBALS( - char *s; - char *c; + char *s, *c; ) void su_main() { - char *name, *passhash = 0, **argu, **argv; + char *name, **shadow, *passhash = 0, **argu, **argv; struct passwd *up; if (*toys.optargs && !strcmp("-", *toys.optargs)) { @@ -57,17 +56,17 @@ void su_main() loggit(LOG_NOTICE, "%s->%s", getusername(geteuid()), name); if (getuid()) { - struct spwd *shp; - - if (!(shp = getspnam(name))) perror_exit("no '%s'", name); - if (*shp->sp_pwdp != '$') goto deny; + if (!(shadow = get_userline("/etc/shadow", name))) + perror_exit("no '%s'", name); + if (*shadow[1] != '$') goto deny; if (read_password(toybuf, sizeof(toybuf), "Password: ")) goto deny; - passhash = crypt(toybuf, shp->sp_pwdp); + passhash = crypt(toybuf, shadow[1]); + if (!passhash || strcmp(passhash, shadow[1])) name = 0; memset(toybuf, 0, sizeof(toybuf)); - if (!passhash || strcmp(passhash, shp->sp_pwdp)) goto deny; + memset(shadow[1], 0, strlen(shadow[1])); + if (passhash) memset(passhash, 0, strlen(passhash)); + if (!name) goto deny; } - closelog(); - xsetuser(up = xgetpwnam(name)); if (FLAG(m)||FLAG(p)) { @@ -76,15 +75,15 @@ void su_main() } else reset_env(up, FLAG(l)); argv = argu = xmalloc(sizeof(char *)*(toys.optc + 4)); - *(argv++) = TT.s ? TT.s : up->pw_shell; + *argv++ = TT.s ? : up->pw_shell; loggit(LOG_NOTICE, "run %s", *argu); if (FLAG(l)) *(argv++) = "-l"; if (FLAG(c)) { - *(argv++) = "-c"; - *(argv++) = TT.c; + *argv++ = "-c"; + *argv++ = TT.c; } - while ((*(argv++) = *(toys.optargs++))); + while ((*argv++ = *toys.optargs++)); xexec(argu); deny: -- 2.39.2