From ca46cac76757082322d19f736a88cbf81bd70063 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Nov 02 2015 18:20:24 +0000 Subject: Support passwords up to PAM_MAX_RESP_SIZE - 1 with --stdin --- diff --git a/ChangeLog b/ChangeLog index 2e306ee..6c7808b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-02 Miloslav Trmač + + * passwd.c (main): Support passwords up to PAM_MAX_RESP_SIZE - 1 with + --stdin. Fail instead of silently truncating longer passwords. + 2015-05-23 Miloslav Trmač * man/passwd.1: diff --git a/passwd.c b/passwd.c index b1dd114..45acf02 100644 --- a/passwd.c +++ b/passwd.c @@ -479,17 +479,32 @@ main(int argc, const char **argv) /* If we need to read the new password from stdin, read it and switch * to the really-quiet stdin conversation function. */ if (passwd_flags & PASSWD_STDIN) { - char *ptr, newPassword[80]; + /* PAM's documentation says that PAM_MAX_RESP_SIZE is the + * maximum supported length of the password, but in practice + * the code (including examples in the OSF RFC) often truncates + * data at PAM_MAX_RESP_SIZE - 1. So, refuse to use anything + * longer than PAM_MAX_RESP_SIZE - 1, to prevent users from + * setting a password they won't be able to use to log in. */ + char *ptr, newPassword[PAM_MAX_RESP_SIZE]; int i; i = read(STDIN_FILENO, newPassword, - sizeof(newPassword) - 1); + sizeof(newPassword)); if (i < 0) { fprintf(stderr, _("%s: error reading from stdin: %s\n"), progname, strerror(errno)); exit(1); } + if (i == sizeof(newPassword)) { + if (newPassword[i - 1] != '\n') { + fprintf(stderr, + _("%s: password too long, maximum is %zu"), + progname, sizeof(newPassword) - 1); + exit(1); + } + i--; + } newPassword[i] = '\0'; ptr = strchr(newPassword, '\n');