pam_localuser: handle long lines in passwd files properly

Before this change, a long line in the passwd file used to be treated as
several lines which could potentially result to false match and,
consequently, to incorrect PAM_SUCCESS return value.

* modules/pam_localuser/pam_localuser.c (pam_sm_authenticate): Handle
long lines in passwd files properly.
This commit is contained in:
Dmitry V. Levin 2020-05-01 21:44:59 +00:00
parent 378ff91760
commit ed74a6c898

View File

@ -130,13 +130,20 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
return PAM_PERM_DENIED;
}
/* scan the file, using fgets() instead of fgetpwent() because i
* don't want to mess with applications which call fgetpwent() */
/*
* Scan the file using fgets() instead of fgetpwent_r() because
* the latter is not flexible enough in handling long lines
* in passwd files.
*/
ret = PAM_PERM_DENIED;
while(fgets(line, sizeof(line), fp) != NULL) {
while (fgets(line, sizeof(line), fp) != NULL) {
size_t line_len;
const char *str;
if(debug) {
pam_syslog (pamh, LOG_DEBUG, "checking \"%s\"", line);
}
/*
* Does this line start with the user name
* followed by a colon?
@ -146,6 +153,28 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
ret = PAM_SUCCESS;
break;
}
/* Has a newline been read? */
line_len = strlen(line);
if (line_len < sizeof(line) - 1 ||
line[line_len - 1] == '\n') {
/* Yes, continue with the next line. */
continue;
}
/* No, read till the end of this line first. */
while ((str = fgets(line, sizeof(line), fp)) != NULL) {
line_len = strlen(line);
if (line_len == 0 ||
line[line_len - 1] == '\n') {
break;
}
}
if (str == NULL) {
/* fgets returned NULL, we are done. */
break;
}
/* Continue with the next line. */
}
/* okay, we're done */