aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2021-03-27 07:20:38 -0500
committerRob Landley <rob@landley.net>2021-03-27 07:20:38 -0500
commit0202865a1d8d5ffb8f312bf700d74fb4f43f14f5 (patch)
tree954cd9ddc46571c9e969145e7c5cc92d8bb5b967
parentb82dd46f4d756158c2ceaa219d54d51465f53dd3 (diff)
downloadtoybox-0202865a1d8d5ffb8f312bf700d74fb4f43f14f5.tar.gz
More cleanup of chsh.c
-rw-r--r--toys/pending/chsh.c97
1 files changed, 30 insertions, 67 deletions
diff --git a/toys/pending/chsh.c b/toys/pending/chsh.c
index 194946de..c34660f7 100644
--- a/toys/pending/chsh.c
+++ b/toys/pending/chsh.c
@@ -28,93 +28,56 @@ GLOBALS(
void chsh_main()
{
- int i;
FILE *file;
- size_t size, buf_size;
- char *user, *line, *shell, *password, *encrypted;
+ char *user, *line, *shell, *encrypted;
struct passwd *passwd_info;
struct spwd *shadow_info;
-
- // Use max login name size for buffer size
- if (-1 == (buf_size = sysconf(_SC_LOGIN_NAME_MAX))) buf_size = 256;
-
- if (!(user = malloc(buf_size * sizeof(user)))) perror_exit("Failed to allocate memory");
- if (!(shell = malloc(buf_size * sizeof(shell)))) perror_exit("Failed to allocate memory");
- if (!(line = malloc(buf_size * sizeof(line)))) perror_exit("Failed to allocate memory");
- if (MAP_FAILED == (password = mmap(NULL, buf_size, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED | MAP_NORESERVE, -1, 0))) perror_exit("Failed to get memory map");
+ int i;
// Get uid user information, may be discarded later
- if (!(passwd_info = getpwuid(getuid()))) perror_exit("Failed to get passwd record");
if ((user = *toys.optargs)) {
- errno = 0;
- if (!(passwd_info = getpwnam(user)) && !errno) error_exit("Failed to get user info");
-
- // Are we either root or changing our own shell?
- if (getuid() && strcmp(passwd_info->pw_name, user)) error_exit("Permission denied\n");
- } else user = passwd_info->pw_name;
+ passwd_info = xgetpwnam(user);
+ if (geteuid() && strcmp(passwd_info->pw_name, user))
+ error_exit("Permission denied\n");
+ } else {
+ passwd_info = xgetpwuid(getuid());
+ user = passwd_info->pw_name;
+ }
// Get a password, encrypt it, wipe it, and check it
- if (!(shadow_info = getspnam(passwd_info->pw_name))) perror_exit("Failed to get shadow record");
- if (!read_password(password, buf_size, "Password: ")) error_exit("Failed to read password\n");
- if (!(encrypted = crypt(password, shadow_info->sp_pwdp))) perror_exit("Failed to encrypt password");
- memset(password, 0, buf_size);
- if (!munmap(password, buf_size)) perror_exit("Failed to unmap memory");
- if (strcmp(encrypted, shadow_info->sp_pwdp)) perror_exit("Incorrect password");
+ if (mlock(toybuf, sizeof(toybuf))) perror_exit("mlock");
+ if (!(shadow_info = getspnam(passwd_info->pw_name))) perror_exit("getspnam");
+ if (!read_password(toybuf, sizeof(toybuf), "Password: ")) xexit();
+ if (!(encrypted = crypt(toybuf, shadow_info->sp_pwdp))) perror_exit("crypt");
+ memset(toybuf, 0, sizeof(toybuf));
+ munlock(toybuf, sizeof(toybuf)); // prevents memset from "optimizing" away.
+ if (strcmp(encrypted, shadow_info->sp_pwdp)) perror_exit("Bad password");
// Get new shell (either -s or interactive)
- if (!(file = fopen("/etc/shells", "r"))) perror_exit("Failed to open /etc/shells");
+ file = xfopen("/etc/shells", "r");
if (toys.optflags) shell = TT.s;
else {
- xprintf("Changing the login shell for %s\nEnter the new value, or press ENTER for default\n Login shell [%s]: ", user, passwd_info->pw_shell);
-
- errno = 0; size = 0;
- while (EOF != (i = fgetc(stdin))) {
- if (errno) perror_exit("Failed to read character from stdin");
-
- if ('\n' != i) *(shell + size++) = i;
- else {
- *(shell + size) = '\0'; break;
- }
- }
+ xprintf("Changing the login shell for %s\n"
+ "Enter the new value, or press ENTER for default\n"
+ " Login shell [%s]: ", user, passwd_info->pw_shell);
+ if (!(shell = xgetline(stdin))) xexit();
}
- // Is shell in /etc/shells?
- if (strlen(shell)) {
- line = NULL; size = 0; i = 0; errno = 0;
-
- while (EOF != getline(&line, &size, file)) {
- if (errno) perror_exit("Failed to read from /etc/shells");
-
- size = strlen(line) - 1;
- if ('\n' == *(line + size)) *(line + size) = '\0';
-
- if (!strcmp(shell, line)) {
- i = 1; break;
- }
- }
-
- if (!i) error_exit("Shell not found in '/etc/shells'");
- } else {
-
- // Get default shell, ignoring comments and blank lines
- do {
- shell = NULL;
- if (-1 == getline(&shell, &size, file)) perror_exit("Failed to read from /etc/shells");
- } while (*shell != '/');
-
- size = strlen(shell) - 1;
- if ('\n' == *(shell + size)) *(shell + size) = '\0';
- }
+ // Verify supplied shell in /etc/shells, or get default shell
+ if (strlen(shell))
+ while ((line = xgetline(file)) && strcmp(shell, line)) free(line);
+ else do line = xgetline(file); while (line && *line != '/');
+ if (!line) error_exit("Shell not found in '/etc/shells'");
// Update shell and write passwd entry to tempfile
- strncpy(passwd_info->pw_shell, shell, buf_size);
- if (!(file = tmpfile())) perror_exit("Failed to create tempfile");
- if (!putpwent(passwd_info, file)) perror_exit("Failed to write to passwd entry");
+ passwd_info->pw_shell = line;
+ if (!(file = tmpfile())) perror_exit("tmpfile");
+ if (!putpwent(passwd_info, file)) perror_exit("putpwent");
// Move passwd entry from file to string
if (-1 == (i = ftell(file))) perror_exit("Failed to get tempfile offset");
- if (buf_size < i && !realloc(line, i)) perror_exit("Failed to reallocate memory");
+ if (sizeof(toybuf) < i && !realloc(line, i)) perror_exit("Failed to reallocate memory");
rewind(file);
if (fread(line, 1, i, file) < i) perror_exit("Failed to read from tempfile");