diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2020-05-01 21:44:59 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2020-05-21 16:51:52 +0000 |
commit | ed74a6c898df2963d0587262caf6996259025426 (patch) | |
tree | d6b4021361b866dd13b9da04b0cda5c1a89d3b91 /modules/pam_localuser | |
parent | 378ff917604725de6109b2a039de963de1f3245b (diff) | |
download | pam-ed74a6c898df2963d0587262caf6996259025426.tar.gz pam-ed74a6c898df2963d0587262caf6996259025426.tar.bz2 pam-ed74a6c898df2963d0587262caf6996259025426.zip |
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.
Diffstat (limited to 'modules/pam_localuser')
-rw-r--r-- | modules/pam_localuser/pam_localuser.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/modules/pam_localuser/pam_localuser.c b/modules/pam_localuser/pam_localuser.c index 3ce0aaa0..66ca2d08 100644 --- a/modules/pam_localuser/pam_localuser.c +++ b/modules/pam_localuser/pam_localuser.c @@ -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 */ |