package/linux-pam: fix build on musl
authorFabrice Fontaine <fontaine.fabrice@gmail.com>
Sun, 14 Jun 2020 16:55:49 +0000 (18:55 +0200)
committerYann E. MORIN <yann.morin.1998@free.fr>
Sun, 14 Jun 2020 19:47:22 +0000 (21:47 +0200)
Fixes:
 - http://autobuild.buildroot.org/results/2e634e22583f1f54cd4aff4d22942a3bcf4951a2

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
package/linux-pam/0002-fix-build-on-musl.patch [new file with mode: 0644]

diff --git a/package/linux-pam/0002-fix-build-on-musl.patch b/package/linux-pam/0002-fix-build-on-musl.patch
new file mode 100644 (file)
index 0000000..44fcecc
--- /dev/null
@@ -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
+