557fe26951
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
226 lines
6.7 KiB
Diff
226 lines
6.7 KiB
Diff
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
|
|
|