|
@@ -0,0 +1,320 @@
|
|
|
+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
|
|
|
+
|