Switch pam_userdb from BerkeleyDB to GDBM (#2245149 and #1788543)

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
This commit is contained in:
Iker Pedrosa 2023-10-23 12:42:35 +02:00
parent ef58d71cf1
commit 557fe26951
2 changed files with 236 additions and 3 deletions

225
pam-1.5.3-userdb-gdbm.patch Normal file
View File

@ -0,0 +1,225 @@
From 45c2c496dcf89f568b90fcf403af9d63b2361fbd Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
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 <ipedrosa@redhat.com>
---
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 <ndbm.h>
+#elif defined(HAVE_GDBM_H)
+# include <gdbm.h>
#else
# ifdef HAVE_DB_H
# define DB_DBM_HSEARCH 1 /* use the dbm interface */
@@ -40,6 +42,12 @@
#include <security/_pam_macros.h>
#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

View File

@ -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 <ipedrosa@redhat.com> - 1.5.2-4
- Switch pam_userdb from BerkeleyDB to GDBM (#2245149 and #1788543)
* Thu Oct 19 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.3-3
- pam_pwhistory: fix passing NULL filename argument to pwhistory helper