Accepting request 1041656 from Linux-PAM
OBS-URL: https://build.opensuse.org/request/show/1041656 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/pam?expand=0&rev=125
This commit is contained in:
commit
dbcb16eb1c
20423
docbook5.patch
Normal file
20423
docbook5.patch
Normal file
File diff suppressed because it is too large
Load Diff
4632
pam-git.diff
4632
pam-git.diff
File diff suppressed because it is too large
Load Diff
@ -1,194 +0,0 @@
|
||||
From d275f22cf28da287e93b5e5a1fdb8a68b2815982 Mon Sep 17 00:00:00 2001
|
||||
From: Thorsten Kukuk <kukuk@suse.com>
|
||||
Date: Thu, 24 Feb 2022 10:37:32 +0100
|
||||
Subject: [PATCH] pam_access: handle hostnames in access.conf
|
||||
|
||||
According to the manual page, the following entry is valid but does not
|
||||
work:
|
||||
-:root:ALL EXCEPT localhost
|
||||
|
||||
See https://bugzilla.suse.com/show_bug.cgi?id=1019866
|
||||
|
||||
Patched is based on PR#226 from Josef Moellers
|
||||
---
|
||||
modules/pam_access/pam_access.c | 95 ++++++++++++++++++++++++++-------
|
||||
1 file changed, 76 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
|
||||
index 0d033aa20..3cec542be 100644
|
||||
--- a/modules/pam_access/pam_access.c
|
||||
+++ b/modules/pam_access/pam_access.c
|
||||
@@ -640,7 +640,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item)
|
||||
if ((str_len = strlen(string)) > tok_len
|
||||
&& strcasecmp(tok, string + str_len - tok_len) == 0)
|
||||
return YES;
|
||||
- } else if (tok[tok_len - 1] == '.') {
|
||||
+ } else if (tok[tok_len - 1] == '.') { /* internet network numbers (end with ".") */
|
||||
struct addrinfo hint;
|
||||
|
||||
memset (&hint, '\0', sizeof (hint));
|
||||
@@ -681,7 +681,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item)
|
||||
return NO;
|
||||
}
|
||||
|
||||
- /* Assume network/netmask with an IP of a host. */
|
||||
+ /* Assume network/netmask, IP address or hostname. */
|
||||
return network_netmask_match(pamh, tok, string, item);
|
||||
}
|
||||
|
||||
@@ -699,7 +699,7 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string,
|
||||
/*
|
||||
* If the token has the magic value "ALL" the match always succeeds.
|
||||
* Otherwise, return YES if the token fully matches the string.
|
||||
- * "NONE" token matches NULL string.
|
||||
+ * "NONE" token matches NULL string.
|
||||
*/
|
||||
|
||||
if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
|
||||
@@ -717,7 +717,8 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string,
|
||||
|
||||
/* network_netmask_match - match a string against one token
|
||||
* where string is a hostname or ip (v4,v6) address and tok
|
||||
- * represents either a single ip (v4,v6) address or a network/netmask
|
||||
+ * represents either a hostname, a single ip (v4,v6) address
|
||||
+ * or a network/netmask
|
||||
*/
|
||||
static int
|
||||
network_netmask_match (pam_handle_t *pamh,
|
||||
@@ -726,10 +727,12 @@ network_netmask_match (pam_handle_t *pamh,
|
||||
char *netmask_ptr;
|
||||
char netmask_string[MAXHOSTNAMELEN + 1];
|
||||
int addr_type;
|
||||
+ struct addrinfo *ai = NULL;
|
||||
|
||||
if (item->debug)
|
||||
- pam_syslog (pamh, LOG_DEBUG,
|
||||
+ pam_syslog (pamh, LOG_DEBUG,
|
||||
"network_netmask_match: tok=%s, item=%s", tok, string);
|
||||
+
|
||||
/* OK, check if tok is of type addr/mask */
|
||||
if ((netmask_ptr = strchr(tok, '/')) != NULL)
|
||||
{
|
||||
@@ -763,54 +766,108 @@ network_netmask_match (pam_handle_t *pamh,
|
||||
netmask_ptr = number_to_netmask(netmask, addr_type,
|
||||
netmask_string, MAXHOSTNAMELEN);
|
||||
}
|
||||
- }
|
||||
+
|
||||
+ /*
|
||||
+ * Construct an addrinfo list from the IP address.
|
||||
+ * This should not fail as the input is a correct IP address...
|
||||
+ */
|
||||
+ if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
|
||||
+ {
|
||||
+ return NO;
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
- /* NO, then check if it is only an addr */
|
||||
- if (isipaddr(tok, NULL, NULL) != YES)
|
||||
+ {
|
||||
+ /*
|
||||
+ * It is either an IP address or a hostname.
|
||||
+ * Let getaddrinfo sort everything out
|
||||
+ */
|
||||
+ if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
|
||||
{
|
||||
+ pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", tok);
|
||||
+
|
||||
return NO;
|
||||
}
|
||||
+ netmask_ptr = NULL;
|
||||
+ }
|
||||
|
||||
if (isipaddr(string, NULL, NULL) != YES)
|
||||
{
|
||||
- /* Assume network/netmask with a name of a host. */
|
||||
struct addrinfo hint;
|
||||
|
||||
+ /* Assume network/netmask with a name of a host. */
|
||||
memset (&hint, '\0', sizeof (hint));
|
||||
hint.ai_flags = AI_CANONNAME;
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
|
||||
if (item->gai_rv != 0)
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
return NO;
|
||||
+ }
|
||||
else if (!item->res &&
|
||||
(item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0)
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
return NO;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
struct addrinfo *runp = item->res;
|
||||
+ struct addrinfo *runp1;
|
||||
|
||||
while (runp != NULL)
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
- DIAG_PUSH_IGNORE_CAST_ALIGN;
|
||||
- inet_ntop (runp->ai_family,
|
||||
- runp->ai_family == AF_INET
|
||||
- ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr
|
||||
- : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
|
||||
- buf, sizeof (buf));
|
||||
- DIAG_POP_IGNORE_CAST_ALIGN;
|
||||
+ if (getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
+ return NO;
|
||||
+ }
|
||||
|
||||
- if (are_addresses_equal(buf, tok, netmask_ptr))
|
||||
+ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next)
|
||||
{
|
||||
- return YES;
|
||||
+ char buf1[INET6_ADDRSTRLEN];
|
||||
+
|
||||
+ if (runp->ai_family != runp1->ai_family)
|
||||
+ continue;
|
||||
+
|
||||
+ if (getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
+ return NO;
|
||||
+ }
|
||||
+
|
||||
+ if (are_addresses_equal (buf, buf1, netmask_ptr))
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
+ return YES;
|
||||
+ }
|
||||
}
|
||||
runp = runp->ai_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
- return (are_addresses_equal(string, tok, netmask_ptr));
|
||||
+ {
|
||||
+ struct addrinfo *runp1;
|
||||
+
|
||||
+ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next)
|
||||
+ {
|
||||
+ char buf1[INET6_ADDRSTRLEN];
|
||||
+
|
||||
+ (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST);
|
||||
+
|
||||
+ if (are_addresses_equal(string, buf1, netmask_ptr))
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
+ return YES;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ freeaddrinfo(ai);
|
||||
|
||||
return NO;
|
||||
}
|
14
pam.changes
14
pam.changes
@ -1,3 +1,17 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Dec 6 16:43:49 UTC 2022 - Thorsten Kukuk <kukuk@suse.com>
|
||||
|
||||
- pam_pwhistory-docu.patch, docbook5.patch: convert docu to
|
||||
docbook5
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Dec 1 13:51:35 UTC 2022 - Thorsten Kukuk <kukuk@suse.com>
|
||||
|
||||
- pam-git.diff: update to current git
|
||||
- obsoletes pam-hostnames-in-access_conf.patch
|
||||
- obsoletes tst-pam_env-retval.c
|
||||
- pam_env_econf.patch refresh
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Nov 22 15:24:12 UTC 2022 - Thorsten Kukuk <kukuk@suse.com>
|
||||
|
||||
|
15
pam.spec
15
pam.spec
@ -64,14 +64,14 @@ Source12: pam-login_defs-check.sh
|
||||
Source13: pam.tmpfiles
|
||||
Source14: Linux-PAM-%{version}-docs.tar.xz.asc
|
||||
Source15: Linux-PAM-%{version}.tar.xz.asc
|
||||
Source16: tst-pam_env-retval.c
|
||||
Patch1: pam-limit-nproc.patch
|
||||
Patch2: pam-hostnames-in-access_conf.patch
|
||||
Patch3: pam-xauth_ownership.patch
|
||||
Patch4: pam-bsc1177858-dont-free-environment-string.patch
|
||||
Patch10: pam_xauth_data.3.xml.patch
|
||||
Patch11: pam-git.diff
|
||||
Patch12: pam_env_econf.patch
|
||||
Patch13: pam_pwhistory-docu.patch
|
||||
Patch14: docbook5.patch
|
||||
BuildRequires: audit-devel
|
||||
BuildRequires: bison
|
||||
BuildRequires: flex
|
||||
@ -147,7 +147,7 @@ Summary: Manualpages for Pluggable Authentication Modules
|
||||
Group: Documentation/HTML
|
||||
Provides: pam:/%{_mandir}/man8/PAM.8.gz
|
||||
BuildArch: noarch
|
||||
BuildRequires: docbook-xsl-stylesheets
|
||||
BuildRequires: docbook5-xsl-stylesheets
|
||||
BuildRequires: elinks
|
||||
BuildRequires: xmlgraphics-fop
|
||||
|
||||
@ -177,14 +177,16 @@ building both PAM-aware applications and modules for use with PAM.
|
||||
%prep
|
||||
%setup -q -n Linux-PAM-%{version} -b 1
|
||||
cp -a %{SOURCE12} .
|
||||
cp %{SOURCE16} ./modules/pam_env
|
||||
%patch11 -p1
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch10 -p1
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
%if %{build_doc}
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
%endif
|
||||
|
||||
%build
|
||||
bash ./pam-login_defs-check.sh
|
||||
@ -343,6 +345,7 @@ done
|
||||
%config(noreplace) %{_pam_secconfdir}/time.conf
|
||||
%config(noreplace) %{_pam_secconfdir}/namespace.conf
|
||||
%config(noreplace) %{_pam_secconfdir}/namespace.init
|
||||
%config(noreplace) %{_pam_secconfdir}/pwhistory.conf
|
||||
%dir %{_pam_secconfdir}/namespace.d
|
||||
%{_libdir}/libpam.so.0
|
||||
%{_libdir}/libpam.so.%{libpam_so_version}
|
||||
|
File diff suppressed because it is too large
Load Diff
264
pam_pwhistory-docu.patch
Normal file
264
pam_pwhistory-docu.patch
Normal file
@ -0,0 +1,264 @@
|
||||
diff --git a/modules/pam_pwhistory/Makefile.am b/modules/pam_pwhistory/Makefile.am
|
||||
index 8a4dbcb2..c29a8e11 100644
|
||||
--- a/modules/pam_pwhistory/Makefile.am
|
||||
+++ b/modules/pam_pwhistory/Makefile.am
|
||||
@@ -9,9 +9,10 @@ MAINTAINERCLEANFILES = $(MANS) README
|
||||
EXTRA_DIST = $(XMLS)
|
||||
|
||||
if HAVE_DOC
|
||||
-dist_man_MANS = pam_pwhistory.8 pwhistory_helper.8
|
||||
+dist_man_MANS = pam_pwhistory.8 pwhistory_helper.8 pwhistory.conf.5
|
||||
endif
|
||||
-XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml
|
||||
+XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml \
|
||||
+ pwhistory.conf.5.xml
|
||||
dist_check_SCRIPTS = tst-pam_pwhistory
|
||||
TESTS = $(dist_check_SCRIPTS)
|
||||
|
||||
diff --git a/modules/pam_pwhistory/pam_pwhistory.8.xml b/modules/pam_pwhistory/pam_pwhistory.8.xml
|
||||
index d88115c2..2a8fa7f6 100644
|
||||
--- a/modules/pam_pwhistory/pam_pwhistory.8.xml
|
||||
+++ b/modules/pam_pwhistory/pam_pwhistory.8.xml
|
||||
@@ -36,6 +36,12 @@
|
||||
<arg choice="opt">
|
||||
authtok_type=<replaceable>STRING</replaceable>
|
||||
</arg>
|
||||
+ <arg choice="opt">
|
||||
+ file=<replaceable>/path/filename</replaceable>
|
||||
+ </arg>
|
||||
+ <arg choice="opt">
|
||||
+ conf=<replaceable>/path/to/config-file</replaceable>
|
||||
+ </arg>
|
||||
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
@@ -104,7 +110,7 @@
|
||||
<listitem>
|
||||
<para>
|
||||
The last <replaceable>N</replaceable> passwords for each
|
||||
- user are saved in <filename>/etc/security/opasswd</filename>.
|
||||
+ user are saved.
|
||||
The default is <emphasis>10</emphasis>. Value of
|
||||
<emphasis>0</emphasis> makes the module to keep the existing
|
||||
contents of the <filename>opasswd</filename> file unchanged.
|
||||
@@ -137,7 +143,39 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>file=<replaceable>/path/filename</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Store password history in file <filename>/path/filename</filename>
|
||||
+ rather than the default location. The default location is
|
||||
+ <filename>/etc/security/opasswd</filename>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>conf=<replaceable>/path/to/config-file</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Use another configuration file instead of the default
|
||||
+ <filename>/etc/security/pwhistory.conf</filename>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
</variablelist>
|
||||
+ <para>
|
||||
+ The options for configuring the module behavior are described in the
|
||||
+ <citerefentry><refentrytitle>pwhistory.conf</refentrytitle>
|
||||
+ <manvolnum>5</manvolnum></citerefentry> manual page. The options
|
||||
+ specified on the module command line override the values from the
|
||||
+ configuration file.
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_pwhistory-types">
|
||||
@@ -213,7 +251,7 @@ password required pam_unix.so use_authtok
|
||||
<varlistentry>
|
||||
<term><filename>/etc/security/opasswd</filename></term>
|
||||
<listitem>
|
||||
- <para>File with password history</para>
|
||||
+ <para>Default file with password history</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
@@ -222,6 +260,9 @@ password required pam_unix.so use_authtok
|
||||
<refsect1 id='pam_pwhistory-see_also'>
|
||||
<title>SEE ALSO</title>
|
||||
<para>
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pwhistory.conf</refentrytitle><manvolnum>5</manvolnum>
|
||||
+ </citerefentry>,
|
||||
<citerefentry>
|
||||
<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
|
||||
</citerefentry>,
|
||||
diff --git a/modules/pam_pwhistory/pwhistory.conf.5.xml b/modules/pam_pwhistory/pwhistory.conf.5.xml
|
||||
new file mode 100644
|
||||
index 00000000..bac5ffed
|
||||
--- /dev/null
|
||||
+++ b/modules/pam_pwhistory/pwhistory.conf.5.xml
|
||||
@@ -0,0 +1,155 @@
|
||||
+<?xml version="1.0" encoding='UTF-8'?>
|
||||
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
|
||||
+
|
||||
+<refentry id="pwhistory.conf">
|
||||
+
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>pwhistory.conf</refentrytitle>
|
||||
+ <manvolnum>5</manvolnum>
|
||||
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv id="pwhistory.conf-name">
|
||||
+ <refname>pwhistory.conf</refname>
|
||||
+ <refpurpose>pam_pwhistory configuration file</refpurpose>
|
||||
+ </refnamediv>
|
||||
+
|
||||
+ <refsect1 id="pwhistory.conf-description">
|
||||
+
|
||||
+ <title>DESCRIPTION</title>
|
||||
+ <para>
|
||||
+ <emphasis remap='B'>pwhistory.conf</emphasis> provides a way to configure the
|
||||
+ default settings for saving the last passwords for each user.
|
||||
+ This file is read by the <emphasis>pam_pwhistory</emphasis> module and is the
|
||||
+ preferred method over configuring <emphasis>pam_pwhistory</emphasis> directly.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ The file has a very simple <emphasis>name = value</emphasis> format with possible comments
|
||||
+ starting with <emphasis>#</emphasis> character. The whitespace at the beginning of line, end
|
||||
+ of line, and around the <emphasis>=</emphasis> sign is ignored.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pwhistory.conf-options">
|
||||
+
|
||||
+ <title>OPTIONS</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>debug</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Turns on debugging via
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
|
||||
+ </citerefentry>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>enforce_for_root</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ If this option is set, the check is enforced for root, too.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>remember=<replaceable>N</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ The last <replaceable>N</replaceable> passwords for each
|
||||
+ user are saved.
|
||||
+ The default is <emphasis>10</emphasis>. Value of
|
||||
+ <emphasis>0</emphasis> makes the module to keep the existing
|
||||
+ contents of the <filename>opasswd</filename> file unchanged.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>retry=<replaceable>N</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Prompt user at most <replaceable>N</replaceable> times
|
||||
+ before returning with error. The default is 1.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>file=<replaceable>/path/filename</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Store password history in file
|
||||
+ <replaceable>/path/filename</replaceable> rather than the default
|
||||
+ location. The default location is
|
||||
+ <filename>/etc/security/opasswd</filename>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pwhistory.conf-examples'>
|
||||
+ <title>EXAMPLES</title>
|
||||
+ <para>
|
||||
+ /etc/security/pwhistory.conf file example:
|
||||
+ </para>
|
||||
+ <programlisting>
|
||||
+debug
|
||||
+remember=5
|
||||
+file=/tmp/opasswd
|
||||
+ </programlisting>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pwhistory.conf-files">
|
||||
+ <title>FILES</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><filename>/etc/security/pwhistory.conf</filename></term>
|
||||
+ <listitem>
|
||||
+ <para>the config file for custom options</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pwhistory.conf-see_also'>
|
||||
+ <title>SEE ALSO</title>
|
||||
+ <para>
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pwhistory</refentrytitle><manvolnum>8</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam_pwhistory</refentrytitle><manvolnum>8</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 id='pwhistory.conf-author'>
|
||||
+ <title>AUTHOR</title>
|
||||
+ <para>
|
||||
+ pam_pwhistory was written by Thorsten Kukuk. The support for
|
||||
+ pwhistory.conf was written by Iker Pedrosa.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+</refentry>
|
||||
|
@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Check pam_env return values.
|
||||
*
|
||||
* Copyright (c) 2020-2022 Dmitry V. Levin <ldv@altlinux.org>
|
||||
* Copyright (c) 2022 Stefan Schubert <schubi@suse.de>
|
||||
*/
|
||||
|
||||
#include "test_assert.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
#define MODULE_NAME "pam_env"
|
||||
#define TEST_NAME "tst-" MODULE_NAME "-retval"
|
||||
#define TEST_NAME_DIR TEST_NAME ".dir"
|
||||
|
||||
static const char service_file[] = TEST_NAME ".service";
|
||||
static const char missing_file[] = TEST_NAME ".missing";
|
||||
static const char dir[] = TEST_NAME_DIR;
|
||||
static const char dir_usr[] = TEST_NAME_DIR "/usr";
|
||||
static const char dir_usr_etc[] = TEST_NAME_DIR "/usr/etc";
|
||||
static const char dir_usr_etc_security[] = TEST_NAME_DIR "/usr/etc/security";
|
||||
static const char my_conf[] = TEST_NAME ".conf";
|
||||
static const char my_env[] = TEST_NAME ".env";
|
||||
static const char usr_env[] = TEST_NAME_DIR "/usr/etc/environment";
|
||||
static const char usr_conf[] = TEST_NAME_DIR "/usr/etc/security/pam_env.conf";
|
||||
|
||||
static struct pam_conv conv;
|
||||
|
||||
static void
|
||||
setup(void)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
ASSERT_EQ(0, mkdir(dir, 0755));
|
||||
ASSERT_EQ(0, mkdir(dir_usr, 0755));
|
||||
ASSERT_EQ(0, mkdir(dir_usr_etc, 0755));
|
||||
ASSERT_EQ(0, mkdir(dir_usr_etc_security, 0755));
|
||||
|
||||
ASSERT_NE(NULL, fp = fopen(my_conf, "w"));
|
||||
ASSERT_LT(0, fprintf(fp,
|
||||
"EDITOR\tDEFAULT=vim\n"
|
||||
"PAGER\tDEFAULT=more\n"));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
ASSERT_NE(NULL, fp = fopen(my_env, "w"));
|
||||
ASSERT_LT(0, fprintf(fp,
|
||||
"test_value=foo\n"
|
||||
"test2_value=bar\n"));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
ASSERT_NE(NULL, fp = fopen(usr_env, "w"));
|
||||
ASSERT_LT(0, fprintf(fp,
|
||||
"usr_etc_test=foo\n"
|
||||
"usr_etc_test2=bar\n"));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
ASSERT_NE(NULL, fp = fopen(usr_conf, "w"));
|
||||
ASSERT_LT(0, fprintf(fp,
|
||||
"PAGER DEFAULT=emacs\n"
|
||||
"MANPAGER DEFAULT=less\n"));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup(void)
|
||||
{
|
||||
ASSERT_EQ(0, unlink(my_conf));
|
||||
ASSERT_EQ(0, unlink(my_env));
|
||||
ASSERT_EQ(0, unlink(usr_env));
|
||||
ASSERT_EQ(0, unlink(usr_conf));
|
||||
ASSERT_EQ(0, rmdir(dir_usr_etc_security));
|
||||
ASSERT_EQ(0, rmdir(dir_usr_etc));
|
||||
ASSERT_EQ(0, rmdir(dir_usr));
|
||||
ASSERT_EQ(0, rmdir(dir));
|
||||
}
|
||||
|
||||
static void
|
||||
check_array(const char **array1, char **array2)
|
||||
{
|
||||
for (const char **a1 = array1; *a1 != NULL; ++a1) {
|
||||
char **a2;
|
||||
for (a2 = array2; *a2 != NULL; ++a2) {
|
||||
if (strcmp(*a1, *a2) == 0)
|
||||
break;
|
||||
}
|
||||
ASSERT_NE(NULL, *a2);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_env(const char **list)
|
||||
{
|
||||
pam_handle_t *pamh = NULL;
|
||||
|
||||
ASSERT_EQ(PAM_SUCCESS,
|
||||
pam_start_confdir(service_file, "", &conv, ".", &pamh));
|
||||
ASSERT_NE(NULL, pamh);
|
||||
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_open_session(pamh, 0));
|
||||
|
||||
char **env_list = pam_getenvlist(pamh);
|
||||
ASSERT_NE(NULL, env_list);
|
||||
|
||||
check_array(list, env_list);
|
||||
|
||||
for (char **e = env_list; *e != NULL; ++e)
|
||||
free(*e);
|
||||
free(env_list);
|
||||
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_close_session(pamh, 0));
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
pam_handle_t *pamh = NULL;
|
||||
FILE *fp;
|
||||
char cwd[PATH_MAX];
|
||||
|
||||
ASSERT_NE(NULL, getcwd(cwd, sizeof(cwd)));
|
||||
|
||||
setup();
|
||||
|
||||
/*
|
||||
* When conffile= specifies a missing file, all methods except
|
||||
* pam_sm_acct_mgmt and pam_sm_chauthtok return PAM_IGNORE.
|
||||
* The return code of the stack where every module returns PAM_IGNORE
|
||||
* is PAM_PERM_DENIED.
|
||||
*/
|
||||
ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||||
ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||||
"auth required %s/.libs/%s.so conffile=%s/%s\n"
|
||||
"account required %s/.libs/%s.so conffile=%s/%s\n"
|
||||
"password required %s/.libs/%s.so conffile=%s/%s\n"
|
||||
"session required %s/.libs/%s.so conffile=%s/%s\n",
|
||||
cwd, MODULE_NAME, cwd, missing_file,
|
||||
cwd, MODULE_NAME, cwd, missing_file,
|
||||
cwd, MODULE_NAME, cwd, missing_file,
|
||||
cwd, MODULE_NAME, cwd, missing_file));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
ASSERT_EQ(PAM_SUCCESS,
|
||||
pam_start_confdir(service_file, "", &conv, ".", &pamh));
|
||||
ASSERT_NE(NULL, pamh);
|
||||
ASSERT_EQ(PAM_PERM_DENIED, pam_authenticate(pamh, 0));
|
||||
ASSERT_EQ(PAM_PERM_DENIED, pam_setcred(pamh, 0));
|
||||
ASSERT_EQ(PAM_SERVICE_ERR, pam_acct_mgmt(pamh, 0));
|
||||
ASSERT_EQ(PAM_SERVICE_ERR, pam_chauthtok(pamh, 0));
|
||||
ASSERT_EQ(PAM_PERM_DENIED, pam_open_session(pamh, 0));
|
||||
ASSERT_EQ(PAM_PERM_DENIED, pam_close_session(pamh, 0));
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||||
pamh = NULL;
|
||||
|
||||
/*
|
||||
* When conffile= specifies a missing file, all methods except
|
||||
* pam_sm_acct_mgmt and pam_sm_chauthtok return PAM_IGNORE.
|
||||
* pam_permit is added after pam_env to convert PAM_IGNORE to PAM_SUCCESS.
|
||||
*/
|
||||
ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||||
ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||||
"auth required %s/.libs/%s.so conffile=%s/%s\n"
|
||||
"auth required %s/../pam_permit/.libs/pam_permit.so\n"
|
||||
"account required %s/.libs/%s.so conffile=%s/%s\n"
|
||||
"account required %s/../pam_permit/.libs/pam_permit.so\n"
|
||||
"password required %s/.libs/%s.so conffile=%s/%s\n"
|
||||
"password required %s/../pam_permit/.libs/pam_permit.so\n"
|
||||
"session required %s/.libs/%s.so conffile=%s/%s\n"
|
||||
"session required %s/../pam_permit/.libs/pam_permit.so\n",
|
||||
cwd, MODULE_NAME, cwd, missing_file, cwd,
|
||||
cwd, MODULE_NAME, cwd, missing_file, cwd,
|
||||
cwd, MODULE_NAME, cwd, missing_file, cwd,
|
||||
cwd, MODULE_NAME, cwd, missing_file, cwd));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
ASSERT_EQ(PAM_SUCCESS,
|
||||
pam_start_confdir(service_file, "", &conv, ".", &pamh));
|
||||
ASSERT_NE(NULL, pamh);
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_authenticate(pamh, 0));
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_setcred(pamh, 0));
|
||||
ASSERT_EQ(PAM_SERVICE_ERR, pam_acct_mgmt(pamh, 0));
|
||||
ASSERT_EQ(PAM_SERVICE_ERR, pam_chauthtok(pamh, 0));
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_open_session(pamh, 0));
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_close_session(pamh, 0));
|
||||
ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||||
pamh = NULL;
|
||||
|
||||
/*
|
||||
* conffile= specifies an existing file,
|
||||
* envfile= specifies an empty file.
|
||||
*/
|
||||
ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||||
ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||||
"session required %s/.libs/%s.so"
|
||||
" conffile=%s/%s envfile=%s\n",
|
||||
cwd, MODULE_NAME,
|
||||
cwd, my_conf, "/dev/null"));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
const char *env1[] = { "EDITOR=vim", "PAGER=more", NULL };
|
||||
check_env(env1);
|
||||
|
||||
/*
|
||||
* conffile= specifies an empty file,
|
||||
* envfile= specifies an existing file.
|
||||
*/
|
||||
ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||||
ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||||
"session required %s/.libs/%s.so"
|
||||
" conffile=%s envfile=%s/%s\n",
|
||||
cwd, MODULE_NAME,
|
||||
"/dev/null", cwd, my_env));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
const char *env2[] = { "test_value=foo", "test2_value=bar", NULL };
|
||||
check_env(env2);
|
||||
|
||||
#if defined (USE_ECONF) && defined (VENDORDIR)
|
||||
|
||||
/* envfile is a directory. So values will be read from {TEST_NAME_DIR}/usr/etc and {TEST_NAME_DIR}/etc */
|
||||
ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||||
ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||||
"session required %s/.libs/%s.so"
|
||||
" conffile=%s envfile=%s/%s/\n",
|
||||
cwd, MODULE_NAME,
|
||||
"/dev/null",
|
||||
cwd, dir));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
const char *env3[] = {"usr_etc_test=foo", "usr_etc_test2=bar", NULL};
|
||||
check_env(env3);
|
||||
|
||||
/* conffile is a directory. So values will be read from {TEST_NAME_DIR}/usr/etc and {TEST_NAME_DIR}/etc */
|
||||
ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||||
ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||||
"session required %s/.libs/%s.so"
|
||||
" conffile=%s/%s/ envfile=%s\n",
|
||||
cwd, MODULE_NAME,
|
||||
cwd, dir,
|
||||
"/dev/null"));
|
||||
ASSERT_EQ(0, fclose(fp));
|
||||
|
||||
const char *env4[] = {"PAGER=emacs", "MANPAGER=less", NULL};
|
||||
check_env(env4);
|
||||
|
||||
#endif
|
||||
|
||||
/* cleanup */
|
||||
cleanup();
|
||||
ASSERT_EQ(0, unlink(service_file));
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user