aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@strace.io>2023-11-07 08:00:00 +0000
committerDmitry V. Levin <ldv@strace.io>2023-11-14 23:25:00 +0000
commit2cae0f5c6757a66602546d76d51a4ba9bb28b2b2 (patch)
tree99a80a13dc8861cdde1b8cf564b0ce51a59399e6
parent6a4bf999a7bd5da780fa4157d4397548ffe0c30f (diff)
downloadpam-2cae0f5c6757a66602546d76d51a4ba9bb28b2b2.tar.gz
pam-2cae0f5c6757a66602546d76d51a4ba9bb28b2b2.tar.bz2
pam-2cae0f5c6757a66602546d76d51a4ba9bb28b2b2.zip
pam_canonicalize_user: new module to canonicalize user name
This module uses the name of the user obtained via pam_get_user(3) as a key to query the password database, and replaces PAM_USER with the pw_name value that has been returned. The main usage scenario is systems where a user name is used in several distinct authentication systems, some of them being case sensitive while others are not. * configure.ac (AC_CONFIG_FILES): Add modules/pam_canonicalize_user/Makefile. * doc/sag/pam_canonicalize_user.xml: New file. * doc/sag/Linux-PAM_SAG.xml: Add a reference to pam_canonicalize_user.xml. * modules/Makefile.am (SUBDIRS): Add pam_canonicalize_user. * modules/pam_canonicalize_user/Makefile.am: New file. * modules/pam_canonicalize_user/README.xml: New file. * modules/pam_canonicalize_user/pam_canonicalize_user.8.xml: New file. * modules/pam_canonicalize_user/pam_canonicalize_user.c: New file. * modules/pam_canonicalize_user/tst-pam_canonicalize_user: New file.
-rw-r--r--configure.ac3
-rw-r--r--doc/sag/Linux-PAM_SAG.xml3
-rw-r--r--doc/sag/pam_canonicalize_user.xml24
-rw-r--r--modules/Makefile.am1
-rw-r--r--modules/pam_canonicalize_user/Makefile.am33
-rw-r--r--modules/pam_canonicalize_user/README.xml27
-rw-r--r--modules/pam_canonicalize_user/pam_canonicalize_user.8.xml137
-rw-r--r--modules/pam_canonicalize_user/pam_canonicalize_user.c76
-rwxr-xr-xmodules/pam_canonicalize_user/tst-pam_canonicalize_user2
9 files changed, 304 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index b6a8d6fb..df95d9bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -768,7 +768,8 @@ AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile
Make.xml.rules \
modules/Makefile \
modules/pam_access/Makefile \
- modules/pam_debug/Makefile modules/pam_deny/Makefile \
+ modules/pam_canonicalize_user/Makefile \
+ modules/pam_debug/Makefile modules/pam_deny/Makefile \
modules/pam_echo/Makefile modules/pam_env/Makefile \
modules/pam_faildelay/Makefile modules/pam_faillock/Makefile \
modules/pam_filter/Makefile modules/pam_filter/upperLOWER/Makefile \
diff --git a/doc/sag/Linux-PAM_SAG.xml b/doc/sag/Linux-PAM_SAG.xml
index 952f224b..e49d7951 100644
--- a/doc/sag/Linux-PAM_SAG.xml
+++ b/doc/sag/Linux-PAM_SAG.xml
@@ -378,6 +378,7 @@ session required pam_warn.so
coming with Linux-PAM.
</para>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_access.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_canonicalize_user.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_debug.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_deny.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_echo.xml"/>
@@ -516,4 +517,4 @@ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
</programlisting>
</chapter>
-</book> \ No newline at end of file
+</book>
diff --git a/doc/sag/pam_canonicalize_user.xml b/doc/sag/pam_canonicalize_user.xml
new file mode 100644
index 00000000..8c42f394
--- /dev/null
+++ b/doc/sag/pam_canonicalize_user.xml
@@ -0,0 +1,24 @@
+<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="sag-pam_canonicalize_user">
+ <title>pam_canonicalize_user - get user name and canonicalize it</title>
+ <cmdsynopsis sepchar=" ">
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../modules/pam_canonicalize_user/pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-cmdsynopsis")/*)'/>
+ </cmdsynopsis>
+ <section xml:id="sag-pam_canonicalize_user-description">
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../modules/pam_canonicalize_user/pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-description")/*)'/>
+ </section>
+ <section xml:id="sag-pam_canonicalize_user-options">
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../modules/pam_canonicalize_user/pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-options")/*)'/>
+ </section>
+ <section xml:id="sag-pam_canonicalize_user-types">
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../modules/pam_canonicalize_user/pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-types")/*)'/>
+ </section>
+ <section xml:id="sag-pam_canonicalize_user-return_values">
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../modules/pam_canonicalize_user/pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-return_values")/*)'/>
+ </section>
+ <section xml:id="sag-pam_canonicalize_user-examples">
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../modules/pam_canonicalize_user/pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-examples")/*)'/>
+ </section>
+ <section xml:id="sag-pam_canonicalize_user-author">
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../modules/pam_canonicalize_user/pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-author")/*)'/>
+ </section>
+</section>
diff --git a/modules/Makefile.am b/modules/Makefile.am
index 8da46410..0d83386a 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -44,6 +44,7 @@ endif
SUBDIRS := \
pam_access \
+ pam_canonicalize_user \
pam_debug \
pam_deny \
pam_echo \
diff --git a/modules/pam_canonicalize_user/Makefile.am b/modules/pam_canonicalize_user/Makefile.am
new file mode 100644
index 00000000..04188a13
--- /dev/null
+++ b/modules/pam_canonicalize_user/Makefile.am
@@ -0,0 +1,33 @@
+CLEANFILES = *~
+MAINTAINERCLEANFILES = $(MANS) README
+
+EXTRA_DIST = $(XMLS)
+
+if HAVE_DOC
+dist_man_MANS = pam_canonicalize_user.8
+endif
+XMLS = README.xml pam_canonicalize_user.8.xml
+dist_check_SCRIPTS = tst-pam_canonicalize_user
+TESTS = $(dist_check_SCRIPTS)
+
+securelibdir = $(SECUREDIR)
+if HAVE_VENDORDIR
+secureconfdir = $(VENDOR_SCONFIGDIR)
+else
+secureconfdir = $(SCONFIGDIR)
+endif
+
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
+ $(WARN_CFLAGS)
+AM_LDFLAGS = -no-undefined -avoid-version -module
+if HAVE_VERSIONING
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+endif
+
+securelib_LTLIBRARIES = pam_canonicalize_user.la
+pam_canonicalize_user_la_LIBADD = $(top_builddir)/libpam/libpam.la
+
+if ENABLE_REGENERATE_MAN
+dist_noinst_DATA = README
+-include $(top_srcdir)/Make.xml.rules
+endif
diff --git a/modules/pam_canonicalize_user/README.xml b/modules/pam_canonicalize_user/README.xml
new file mode 100644
index 00000000..293b218b
--- /dev/null
+++ b/modules/pam_canonicalize_user/README.xml
@@ -0,0 +1,27 @@
+<article xmlns="http://docbook.org/ns/docbook" version="5.0">
+
+ <info>
+
+ <title>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-name")/*)'/>
+ </title>
+
+ </info>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-description")/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-options")/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-examples")/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_canonicalize_user.8.xml" xpointer='xpointer(id("pam_canonicalize_user-author")/*)'/>
+ </section>
+
+</article>
diff --git a/modules/pam_canonicalize_user/pam_canonicalize_user.8.xml b/modules/pam_canonicalize_user/pam_canonicalize_user.8.xml
new file mode 100644
index 00000000..832f7ece
--- /dev/null
+++ b/modules/pam_canonicalize_user/pam_canonicalize_user.8.xml
@@ -0,0 +1,137 @@
+<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="pam_canonicalize_user">
+
+ <refmeta>
+ <refentrytitle>pam_canonicalize_user</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="source">Linux-PAM</refmiscinfo>
+ <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv xml:id="pam_canonicalize_user-name">
+ <refname>pam_canonicalize_user</refname>
+ <refpurpose>Get user name and canonicalize it</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis xml:id="pam_canonicalize_user-cmdsynopsis" sepchar=" ">
+ <command>pam_canonicalize_user.so</command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 xml:id="pam_canonicalize_user-description">
+ <title>DESCRIPTION</title>
+ <para>
+ This PAM module uses the name of the user obtained via
+ <citerefentry>
+ <refentrytitle>pam_get_user</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ as a key to query the password database, and replaces
+ <emphasis>PAM_USER</emphasis> with the <emphasis>pw_name</emphasis> value
+ that has been returned.
+ </para>
+ </refsect1>
+
+ <refsect1 xml:id="pam_canonicalize_user-options">
+ <title>OPTIONS</title>
+ <para>This module does not recognise any options.</para>
+ </refsect1>
+
+ <refsect1 xml:id="pam_canonicalize_user-types">
+ <title>MODULE TYPES PROVIDED</title>
+ <para>Only the <option>auth</option> module type is provided.</para>
+ </refsect1>
+
+ <refsect1 xml:id="pam_canonicalize_user-return_values">
+ <title>RETURN VALUES</title>
+ <variablelist>
+ <varlistentry>
+ <term>PAM_IGNORE</term>
+ <listitem>
+ <para>The user name was set successfully.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_USER_UNKNOWN</term>
+ <listitem>
+ <para>The user was not found.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_SYSTEM_ERR</term>
+ <listitem>
+ <para>The application did not supply neither a user name nor a conversation method.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_INCOMPLETE</term>
+ <listitem>
+ <para>The conversation method supplied by the application is waiting for an event.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_CONV_ERR</term>
+ <listitem>
+ <para>The conversation method supplied by the application failed to obtain the user name.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_ABORT</term>
+ <listitem>
+ <para>Error resuming an old conversation.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_BUF_ERR</term>
+ <listitem>
+ <para>Memory buffer error.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 xml:id="pam_canonicalize_user-examples">
+ <title>EXAMPLES</title>
+ <para>
+ Prepend the PAM auth stack with the following line to canonicalize
+ the user name before the authentication:
+ <programlisting>
+ auth required pam_canonicalize_user.so
+ </programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1 xml:id="pam_get_user-see_also">
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>pam_get_user</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam_set_item</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>getpwnam</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 xml:id="pam_canonicalize_user-author">
+ <title>AUTHOR</title>
+ <para>
+ pam_canonicalize_user was written by Dmitry V. Levin &lt;ldv@strace.io&gt;.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/modules/pam_canonicalize_user/pam_canonicalize_user.c b/modules/pam_canonicalize_user/pam_canonicalize_user.c
new file mode 100644
index 00000000..66f794ce
--- /dev/null
+++ b/modules/pam_canonicalize_user/pam_canonicalize_user.c
@@ -0,0 +1,76 @@
+/*
+ * pam_canonicalize_user - get user name and canonicalize it
+ *
+ * Copyright (c) 2023 Dmitry V. Levin <ldv@strace.io>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL
+ * are required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <syslog.h>
+
+#include <security/pam_modules.h>
+#include <security/pam_modutil.h>
+#include <security/pam_ext.h>
+
+int
+pam_sm_authenticate(pam_handle_t *pamh UNUSED, int flags UNUSED,
+ int argc UNUSED, const char **argv UNUSED)
+{
+ const char *user;
+ int rc = pam_get_user(pamh, &user, 0);
+ if (rc != PAM_SUCCESS) {
+ pam_syslog(pamh, LOG_NOTICE, "cannot determine user name: %s",
+ pam_strerror(pamh, rc));
+ return rc == PAM_CONV_AGAIN ? PAM_INCOMPLETE : rc;
+ }
+
+ struct passwd *pw = pam_modutil_getpwnam(pamh, user);
+ if (!pw) {
+ pam_syslog(pamh, LOG_NOTICE, "user unknown");
+ return PAM_USER_UNKNOWN;
+ }
+
+ if (strcmp(user, pw->pw_name) == 0)
+ return PAM_IGNORE;
+
+ rc = pam_set_item(pamh, PAM_USER, pw->pw_name);
+ return rc == PAM_SUCCESS ? PAM_IGNORE : rc;
+}
+
+int
+pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
+ int argc UNUSED, const char **argv UNUSED)
+{
+ return PAM_IGNORE;
+}
diff --git a/modules/pam_canonicalize_user/tst-pam_canonicalize_user b/modules/pam_canonicalize_user/tst-pam_canonicalize_user
new file mode 100755
index 00000000..2d3cb6f3
--- /dev/null
+++ b/modules/pam_canonicalize_user/tst-pam_canonicalize_user
@@ -0,0 +1,2 @@
+#!/bin/sh
+../../tests/tst-dlopen .libs/pam_canonicalize_user.so