| From 295bf7403364b23ab03287ecdd95ea266d6f4d89 Mon Sep 17 00:00:00 2001 |
| From: Fabrice Fontaine <fontaine.fabrice@gmail.com> |
| Date: Thu, 11 Jun 2020 17:39:03 +0200 |
| Subject: [PATCH] fix build on musl |
| |
| Rename check_user_in_passwd from pam_localuser.c to |
| pam_modutil_check_user_in_passwd and use it in pam_faillock.c instead of |
| fgetpwent_r which is not available on musl |
| |
| Fix #236 |
| |
| Fixes: |
| - http://autobuild.buildroot.org/results/0432736ffee376dd84757469434a4bbcfdcdaf4b |
| |
| Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> |
| [Upstream status: https://github.com/linux-pam/linux-pam/pull/237] |
| --- |
| libpam/Makefile.am | 1 + |
| libpam/include/security/pam_modutil.h | 5 ++ |
| libpam/libpam.map | 5 ++ |
| libpam/pam_modutil_check_user_in_passwd.c | 89 +++++++++++++++++++++++ |
| modules/pam_faillock/pam_faillock.c | 37 +--------- |
| modules/pam_localuser/pam_localuser.c | 86 +--------------------- |
| 6 files changed, 103 insertions(+), 120 deletions(-) |
| create mode 100644 libpam/pam_modutil_check_user_in_passwd.c |
| |
| diff --git a/libpam/Makefile.am b/libpam/Makefile.am |
| index 9252a837..a8fc428d 100644 |
| --- a/libpam/Makefile.am |
| +++ b/libpam/Makefile.am |
| @@ -35,6 +35,7 @@ libpam_la_SOURCES = pam_account.c pam_auth.c pam_data.c pam_delay.c \ |
| pam_misc.c pam_password.c pam_prelude.c \ |
| pam_session.c pam_start.c pam_strerror.c \ |
| pam_vprompt.c pam_syslog.c pam_dynamic.c pam_audit.c \ |
| + pam_modutil_check_user_in_passwd.c \ |
| pam_modutil_cleanup.c pam_modutil_getpwnam.c pam_modutil_ioloop.c \ |
| pam_modutil_getgrgid.c pam_modutil_getpwuid.c pam_modutil_getgrnam.c \ |
| pam_modutil_getspnam.c pam_modutil_getlogin.c pam_modutil_ingroup.c \ |
| diff --git a/libpam/include/security/pam_modutil.h b/libpam/include/security/pam_modutil.h |
| index 3a6aec6a..33f87b90 100644 |
| --- a/libpam/include/security/pam_modutil.h |
| +++ b/libpam/include/security/pam_modutil.h |
| @@ -58,6 +58,11 @@ extern "C" { |
| |
| #include <security/_pam_types.h> |
| |
| +extern int PAM_NONNULL((1,2)) |
| +pam_modutil_check_user_in_passwd(pam_handle_t *pamh, |
| + const char *user_name, |
| + const char *file_name); |
| + |
| extern struct passwd * PAM_NONNULL((1,2)) |
| pam_modutil_getpwnam(pam_handle_t *pamh, const char *user); |
| |
| diff --git a/libpam/libpam.map b/libpam/libpam.map |
| index c9690a91..3cc7ef35 100644 |
| --- a/libpam/libpam.map |
| +++ b/libpam/libpam.map |
| @@ -82,3 +82,8 @@ LIBPAM_1.4 { |
| global: |
| pam_start_confdir; |
| } LIBPAM_1.0; |
| + |
| +LIBPAM_MODUTIL_1.4.1 { |
| + global: |
| + pam_modutil_check_user_in_passwd; |
| +} LIBPAM_MODUTIL_1.3.2; |
| diff --git a/libpam/pam_modutil_check_user_in_passwd.c b/libpam/pam_modutil_check_user_in_passwd.c |
| new file mode 100644 |
| index 00000000..b998aa25 |
| --- /dev/null |
| +++ b/libpam/pam_modutil_check_user_in_passwd.c |
| @@ -0,0 +1,89 @@ |
| +#include "pam_modutil_private.h" |
| +#include <security/pam_ext.h> |
| + |
| +#include <stdio.h> |
| +#include <syslog.h> |
| + |
| +int |
| +pam_modutil_check_user_in_passwd(pam_handle_t *pamh, |
| + const char *user_name, |
| + const char *file_name) |
| +{ |
| + int rc; |
| + size_t user_len; |
| + FILE *fp; |
| + char line[BUFSIZ]; |
| + |
| + /* Validate the user name. */ |
| + if ((user_len = strlen(user_name)) == 0) { |
| + pam_syslog(pamh, LOG_NOTICE, "user name is not valid"); |
| + return PAM_SERVICE_ERR; |
| + } |
| + |
| + if (user_len > sizeof(line) - sizeof(":")) { |
| + pam_syslog(pamh, LOG_NOTICE, "user name is too long"); |
| + return PAM_SERVICE_ERR; |
| + } |
| + |
| + if (strchr(user_name, ':') != NULL) { |
| + /* |
| + * "root:x" is not a local user name even if the passwd file |
| + * contains a line starting with "root:x:". |
| + */ |
| + return PAM_PERM_DENIED; |
| + } |
| + |
| + /* Open the passwd file. */ |
| + if (file_name == NULL) { |
| + file_name = "/etc/passwd"; |
| + } |
| + if ((fp = fopen(file_name, "r")) == NULL) { |
| + pam_syslog(pamh, LOG_ERR, "error opening %s: %m", file_name); |
| + return PAM_SERVICE_ERR; |
| + } |
| + |
| + /* |
| + * Scan the file using fgets() instead of fgetpwent_r() because |
| + * the latter is not flexible enough in handling long lines |
| + * in passwd files. |
| + */ |
| + rc = PAM_PERM_DENIED; |
| + while (fgets(line, sizeof(line), fp) != NULL) { |
| + size_t line_len; |
| + const char *str; |
| + |
| + /* |
| + * Does this line start with the user name |
| + * followed by a colon? |
| + */ |
| + if (strncmp(user_name, line, user_len) == 0 && |
| + line[user_len] == ':') { |
| + rc = 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. */ |
| + } |
| + |
| + fclose(fp); |
| + return rc; |
| +} |
| diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c |
| index f592d0a2..8bca46ca 100644 |
| --- a/modules/pam_faillock/pam_faillock.c |
| +++ b/modules/pam_faillock/pam_faillock.c |
| @@ -348,42 +348,7 @@ set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const c |
| static int |
| check_local_user (pam_handle_t *pamh, const char *user) |
| { |
| - struct passwd pw, *pwp; |
| - char buf[16384]; |
| - int found = 0; |
| - FILE *fp; |
| - int errn; |
| - |
| - fp = fopen(PATH_PASSWD, "r"); |
| - if (fp == NULL) { |
| - pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", |
| - PATH_PASSWD); |
| - return -1; |
| - } |
| - |
| - for (;;) { |
| - errn = fgetpwent_r(fp, &pw, buf, sizeof (buf), &pwp); |
| - if (errn == ERANGE) { |
| - pam_syslog(pamh, LOG_WARNING, "%s contains very long lines; corrupted?", |
| - PATH_PASSWD); |
| - break; |
| - } |
| - if (errn != 0) |
| - break; |
| - if (strcmp(pwp->pw_name, user) == 0) { |
| - found = 1; |
| - break; |
| - } |
| - } |
| - |
| - fclose (fp); |
| - |
| - if (errn != 0 && errn != ENOENT) { |
| - pam_syslog(pamh, LOG_ERR, "unable to enumerate local accounts: %m"); |
| - return -1; |
| - } else { |
| - return found; |
| - } |
| + return pam_modutil_check_user_in_passwd(pamh, user, NULL); |
| } |
| |
| static int |
| diff --git a/modules/pam_localuser/pam_localuser.c b/modules/pam_localuser/pam_localuser.c |
| index cb507524..a9f2233c 100644 |
| --- a/modules/pam_localuser/pam_localuser.c |
| +++ b/modules/pam_localuser/pam_localuser.c |
| @@ -45,92 +45,10 @@ |
| #include <unistd.h> |
| |
| #include <security/pam_modules.h> |
| +#include <security/pam_modutil.h> |
| #include <security/pam_ext.h> |
| #include "pam_inline.h" |
| |
| -static int |
| -check_user_in_passwd(pam_handle_t *pamh, const char *user_name, |
| - const char *file_name) |
| -{ |
| - int rc; |
| - size_t user_len; |
| - FILE *fp; |
| - char line[BUFSIZ]; |
| - |
| - /* Validate the user name. */ |
| - if ((user_len = strlen(user_name)) == 0) { |
| - pam_syslog(pamh, LOG_NOTICE, "user name is not valid"); |
| - return PAM_SERVICE_ERR; |
| - } |
| - |
| - if (user_len > sizeof(line) - sizeof(":")) { |
| - pam_syslog(pamh, LOG_NOTICE, "user name is too long"); |
| - return PAM_SERVICE_ERR; |
| - } |
| - |
| - if (strchr(user_name, ':') != NULL) { |
| - /* |
| - * "root:x" is not a local user name even if the passwd file |
| - * contains a line starting with "root:x:". |
| - */ |
| - return PAM_PERM_DENIED; |
| - } |
| - |
| - /* Open the passwd file. */ |
| - if (file_name == NULL) { |
| - file_name = "/etc/passwd"; |
| - } |
| - if ((fp = fopen(file_name, "r")) == NULL) { |
| - pam_syslog(pamh, LOG_ERR, "error opening %s: %m", file_name); |
| - return PAM_SERVICE_ERR; |
| - } |
| - |
| - /* |
| - * Scan the file using fgets() instead of fgetpwent_r() because |
| - * the latter is not flexible enough in handling long lines |
| - * in passwd files. |
| - */ |
| - rc = PAM_PERM_DENIED; |
| - while (fgets(line, sizeof(line), fp) != NULL) { |
| - size_t line_len; |
| - const char *str; |
| - |
| - /* |
| - * Does this line start with the user name |
| - * followed by a colon? |
| - */ |
| - if (strncmp(user_name, line, user_len) == 0 && |
| - line[user_len] == ':') { |
| - rc = 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. */ |
| - } |
| - |
| - fclose(fp); |
| - return rc; |
| -} |
| - |
| int |
| pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, |
| int argc, const char **argv) |
| @@ -173,7 +91,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, |
| return rc == PAM_CONV_AGAIN ? PAM_INCOMPLETE : rc; |
| } |
| |
| - return check_user_in_passwd(pamh, user_name, file_name); |
| + return pam_modutil_check_user_in_passwd(pamh, user_name, file_name); |
| } |
| |
| int |
| -- |
| 2.26.2 |
| |