From 557fe26951bab5103a94b7048ba32cb716aecb99 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 23 Oct 2023 12:42:35 +0200 Subject: [PATCH] Switch pam_userdb from BerkeleyDB to GDBM (#2245149 and #1788543) Signed-off-by: Iker Pedrosa --- pam-1.5.3-userdb-gdbm.patch | 225 ++++++++++++++++++++++++++++++++++++ pam.spec | 14 ++- 2 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 pam-1.5.3-userdb-gdbm.patch diff --git a/pam-1.5.3-userdb-gdbm.patch b/pam-1.5.3-userdb-gdbm.patch new file mode 100644 index 0000000..83fa5c7 --- /dev/null +++ b/pam-1.5.3-userdb-gdbm.patch @@ -0,0 +1,225 @@ +From 45c2c496dcf89f568b90fcf403af9d63b2361fbd Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 10 Jul 2023 12:45:12 +0200 +Subject: [PATCH] pam_userdb: enable GDBM support + +* configure.ac: add `gdbm` option to `enable-db` +* modules/pam_userdb/pam_userdb.c: conditionally provide database access + depending on the database technology + +Signed-off-by: Iker Pedrosa +--- + configure.ac | 10 +++- + modules/pam_userdb/pam_userdb.c | 90 ++++++++++++++++++++++++++++----- + 2 files changed, 86 insertions(+), 14 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 6666b1b2..7565a830 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -436,10 +436,10 @@ if test -n "$opt_randomdev"; then + AC_DEFINE_UNQUOTED(PAM_PATH_RANDOMDEV, "$opt_randomdev", [Random device path.]) + fi + +-dnl check for libdb or libndbm as fallback. Some libndbm compat ++dnl check for libdb or gdbm or libndbm as fallback. Some libndbm compat + dnl libraries are unusable, so try libdb first. + AC_ARG_ENABLE([db], +- AS_HELP_STRING([--enable-db=(db|ndbm|yes|no)],[Default behavior 'yes', which is to check for libdb first, followed by ndbm. Use 'no' to disable db support.]), ++ AS_HELP_STRING([--enable-db=(db|gdbm|ndbm|yes|no)],[Default behavior 'yes', which is to check for libdb first, followed by gdbm and ndbm. Use 'no' to disable db support.]), + WITH_DB=$enableval, WITH_DB=yes) + AC_ARG_WITH([db-uniquename], + AS_HELP_STRING([--with-db-uniquename=extension],[Unique name for db libraries and functions.])) +@@ -451,6 +451,12 @@ if test x"$WITH_DB" != xno ; then + [LIBDB="-ldb$with_db_uniquename"; break]) + LIBS=$old_libs + fi ++ if test x"$WITH_DB" = xgdbm ; then ++ AC_CHECK_LIB([gdbm],[gdbm_store], LIBDB="-lgdbm", LIBDB="") ++ if test -n "$LIBDB" ; then ++ AC_CHECK_HEADERS(gdbm.h) ++ fi ++ fi + if test -z "$LIBDB" ; then + AC_CHECK_LIB([ndbm],[dbm_store], LIBDB="-lndbm", LIBDB="") + if test -n "$LIBDB" ; then +diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c +index 297403b0..0b5e5965 100644 +--- a/modules/pam_userdb/pam_userdb.c ++++ b/modules/pam_userdb/pam_userdb.c +@@ -25,6 +25,8 @@ + + #ifdef HAVE_NDBM_H + # include ++#elif defined(HAVE_GDBM_H) ++# include + #else + # ifdef HAVE_DB_H + # define DB_DBM_HSEARCH 1 /* use the dbm interface */ +@@ -40,6 +42,12 @@ + #include + #include "pam_inline.h" + ++#ifndef HAVE_GDBM_H ++# define COND_UNUSED UNUSED ++#else ++# define COND_UNUSED ++#endif /* HAVE_GDBM_H */ ++ + /* + * Conversation function to obtain the user's password + */ +@@ -129,6 +137,60 @@ _pam_parse (pam_handle_t *pamh, int argc, const char **argv, + return ctrl; + } + ++/* ++ * Database abstraction functions ++ */ ++static void * ++db_open(const char *database, mode_t file_mode) ++{ ++#ifdef HAVE_GDBM_H ++ return gdbm_open(database, 4096, GDBM_READER, file_mode, NULL); ++#else ++ return dbm_open(database, O_RDONLY, file_mode); ++#endif /* HAVE_GDBM_H */ ++} ++ ++static datum ++db_firstkey(void *dbm) ++{ ++#ifdef HAVE_GDBM_H ++ return gdbm_firstkey(dbm); ++#else ++ return dbm_firstkey(dbm); ++#endif /* HAVE_GDBM_H */ ++} ++ ++static datum ++db_nextkey(void *dbm, datum key COND_UNUSED) ++{ ++#ifdef HAVE_GDBM_H ++ return gdbm_nextkey(dbm, key); ++#else ++ return dbm_nextkey(dbm); ++#endif /* HAVE_GDBM_H */ ++} ++ ++static datum ++db_fetch(void *dbm, datum key) ++{ ++#ifdef HAVE_GDBM_H ++ return gdbm_fetch(dbm, key); ++#else ++ return dbm_fetch(dbm, key); ++#endif /* HAVE_GDBM_H */ ++} ++ ++static int ++db_close(void *dbm) ++{ ++#ifdef HAVE_GDBM_H ++ return gdbm_close(dbm); ++#else ++ dbm_close(dbm); ++ return 0; ++#endif /* HAVE_GDBM_H */ ++} ++ + + /* + * Looks up a user name in a database and checks the password +@@ -143,11 +205,15 @@ static int + user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + const char *user, const char *pass, int ctrl) + { ++#ifdef HAVE_GDBM_H ++ GDBM_FILE *dbm; ++#else + DBM *dbm; ++#endif + datum key, data; + + /* Open the DB file. */ +- dbm = dbm_open(database, O_RDONLY, 0644); ++ dbm = db_open(database, 0644); + if (dbm == NULL) { + pam_syslog(pamh, LOG_ERR, + "user_lookup: could not open database `%s': %m", database); +@@ -157,9 +223,9 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + /* dump out the database contents for debugging */ + if (ctrl & PAM_DUMP_ARG) { + pam_syslog(pamh, LOG_INFO, "Database dump:"); +- for (key = dbm_firstkey(dbm); key.dptr != NULL; +- key = dbm_nextkey(dbm)) { +- data = dbm_fetch(dbm, key); ++ for (key = db_firstkey(dbm); key.dptr != NULL; ++ key = db_nextkey(dbm, key)) { ++ data = db_fetch(dbm, key); + pam_syslog(pamh, LOG_INFO, + "key[len=%d] = `%s', data[len=%d] = `%s'", + key.dsize, key.dptr, data.dsize, data.dptr); +@@ -180,7 +246,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + } + + if (key.dptr) { +- data = dbm_fetch(dbm, key); ++ data = db_fetch(dbm, key); + pam_overwrite_n(key.dptr, key.dsize); + free(key.dptr); + } +@@ -196,7 +262,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + + if (ctrl & PAM_KEY_ONLY_ARG) + { +- dbm_close (dbm); ++ db_close (dbm); + return 0; /* found it, data contents don't matter */ + } + +@@ -275,7 +341,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + + } + +- dbm_close(dbm); ++ db_close(dbm); + if (compare == 0) + return 0; /* match */ + else +@@ -290,14 +356,14 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + /* probably we should check dbm_error() here */ + + if ((ctrl & PAM_KEY_ONLY_ARG) == 0) { +- dbm_close(dbm); ++ db_close(dbm); + return 1; /* not key_only, so no entry => no entry for the user */ + } + + /* now handle the key_only case */ +- for (key = dbm_firstkey(dbm); ++ for (key = db_firstkey(dbm); + key.dptr != NULL; +- key = dbm_nextkey(dbm)) { ++ key = db_nextkey(dbm, key)) { + int compare; + /* first compare the user portion (case sensitive) */ + compare = strncmp(key.dptr, user, strlen(user)); +@@ -322,12 +388,12 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, + } + } + if (compare == 0) { +- dbm_close(dbm); ++ db_close(dbm); + return 0; /* match */ + } + } + } +- dbm_close(dbm); ++ db_close(dbm); + if (saw_user) + return -1; /* saw the user, but password mismatch */ + else +-- +2.41.0 + diff --git a/pam.spec b/pam.spec index f595e55..cb1ec58 100644 --- a/pam.spec +++ b/pam.spec @@ -4,7 +4,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.5.3 -Release: 3%{?dist} +Release: 4%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ # - this option is redundant as the BSD license allows that anyway. # pam_timestamp and pam_loginuid modules are GPLv2+. @@ -26,6 +26,7 @@ Patch1: pam-1.5.3-redhat-modules.patch Patch2: pam-1.5.3-noflex.patch Patch3: pam-1.5.3-unix-nomsg.patch Patch4: pam-1.5.3-pwhistory-null-filename-arg.patch +Patch5: pam-1.5.3-userdb-gdbm.patch %{load:%{SOURCE3}} @@ -33,6 +34,8 @@ Patch4: pam-1.5.3-pwhistory-null-filename-arg.patch Requires: libpwquality%{?_isa} Requires: setup Requires: authselect >= 1.3 +Requires: gdbm +Requires: libdb-convert-util Requires: pam-libs%{?_isa} = %{version}-%{release} ### Build Dependencies ### @@ -42,8 +45,8 @@ BuildRequires: automake BuildRequires: bison BuildRequires: flex BuildRequires: gcc +BuildRequires: gdbm-devel BuildRequires: gettext-devel -BuildRequires: libdb-devel BuildRequires: libeconf-devel BuildRequires: libnsl2-devel BuildRequires: libselinux-devel @@ -120,6 +123,7 @@ cp %{SOURCE18} . %patch -P 2 -p1 -b .noflex %patch -P 3 -p1 -b .nomsg %patch -P 4 -p1 -b .pwhistory-null-filename-arg +%patch -P 5 -p1 -b .userdb-gdbm autoreconf -i @@ -133,7 +137,8 @@ autoreconf -i --enable-audit \ --enable-openssl \ --enable-selinux \ - --enable-lastlog + --enable-lastlog \ + --enable-db=gdbm %make_build -C po update-gmo %make_build @@ -355,6 +360,9 @@ done %{_pam_libdir}/libpam_misc.so.%{so_ver}* %changelog +* Mon Oct 23 2023 Iker Pedrosa - 1.5.2-4 +- Switch pam_userdb from BerkeleyDB to GDBM (#2245149 and #1788543) + * Thu Oct 19 2023 Iker Pedrosa - 1.5.3-3 - pam_pwhistory: fix passing NULL filename argument to pwhistory helper