656f9b5474
- pam-hostnames-in-access_conf.patch: update with upstream submission. Fixes several bugs including memory leaks. - Move group.conf and faillock.conf to /usr/etc/security - Update to current git for enhanced vendordir support (pam-git.diff) Obsoletes: - 0001-Include-pam_xauth_data.3.xml-in-source-archive-400.patch - 0002-Only-include-vendordir-in-manual-page-if-set-401.patch - 0003-Use-vendor-specific-limits.conf-as-fallback-402.patch OBS-URL: https://build.opensuse.org/request/show/961064 OBS-URL: https://build.opensuse.org/package/show/Linux-PAM/pam?expand=0&rev=259
1673 lines
57 KiB
Diff
1673 lines
57 KiB
Diff
diff --git a/README b/README
|
||
index 21af8c4c..aa99927e 100644
|
||
--- a/README
|
||
+++ b/README
|
||
@@ -6,7 +6,7 @@ NOTES:
|
||
|
||
How to use it is as follows:
|
||
|
||
-Please look at the ci/install_dependencies.sh for the necessary
|
||
+Please look at the ci/install-dependencies.sh for the necessary
|
||
prerequisite packages to be able to build the Linux-PAM. The script
|
||
is targeted at Debian based Linux distributions so the package
|
||
names and availability might differ on other distributions.
|
||
diff --git a/configure.ac b/configure.ac
|
||
index c06bc7dd..639fc1ad 100644
|
||
--- a/configure.ac
|
||
+++ b/configure.ac
|
||
@@ -259,6 +259,8 @@ AC_MSG_RESULT([Defining \$ISA to "$ISA"])
|
||
AC_ARG_ENABLE(sconfigdir,
|
||
AS_HELP_STRING([--enable-sconfigdir=DIR],[path to module conf files @<:@default=$sysconfdir/security@:>@]),
|
||
SCONFIGDIR=$enableval, SCONFIGDIR=$sysconfdir/security)
|
||
+AC_DEFINE_UNQUOTED([SCONFIGDIR], ["$SCONFIGDIR"],
|
||
+ [Directory for PAM modules system configuration files])
|
||
AC_SUBST(SCONFIGDIR)
|
||
|
||
AC_ARG_ENABLE(pamlocking,
|
||
@@ -507,9 +509,11 @@ AC_ARG_ENABLE([vendordir],
|
||
if test -n "$enable_vendordir"; then
|
||
AC_DEFINE_UNQUOTED([VENDORDIR], ["$enable_vendordir"],
|
||
[Directory for distribution provided configuration files])
|
||
- STRINGPARAM_VENDORDIR="--stringparam vendordir '$enable_vendordir'"
|
||
+ AC_DEFINE_UNQUOTED([VENDOR_SCONFIGDIR], ["$enable_vendordir/security"],
|
||
+ [Directory for PAM modules distribution provided configuration files])
|
||
+ STRINGPARAM_VENDORDIR="--stringparam vendordir '$enable_vendordir' --stringparam profile.condition 'with_vendordir'"
|
||
else
|
||
- STRINGPARAM_VENDORDIR="--stringparam vendordir '<vendordir>'"
|
||
+ STRINGPARAM_VENDORDIR="--stringparam profile.condition 'without_vendordir'"
|
||
fi
|
||
AC_SUBST([STRINGPARAM_VENDORDIR])
|
||
|
||
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
|
||
index 78c891df..c6fd73db 100644
|
||
--- a/doc/man/Makefile.am
|
||
+++ b/doc/man/Makefile.am
|
||
@@ -43,7 +43,7 @@ XMLS = pam.3.xml pam.8.xml \
|
||
pam_item_types_std.inc.xml pam_item_types_ext.inc.xml \
|
||
pam.conf-desc.xml pam.conf-dir.xml pam.conf-syntax.xml \
|
||
misc_conv.3.xml pam_misc_paste_env.3.xml pam_misc_drop_env.3.xml \
|
||
- pam_misc_setenv.3.xml
|
||
+ pam_misc_setenv.3.xml pam_xauth_data.3.xml
|
||
|
||
if ENABLE_REGENERATE_MAN
|
||
PAM.8: pam.8
|
||
diff --git a/doc/man/pam.8.xml b/doc/man/pam.8.xml
|
||
index 464af0e5..8eef665a 100644
|
||
--- a/doc/man/pam.8.xml
|
||
+++ b/doc/man/pam.8.xml
|
||
@@ -158,15 +158,14 @@ closing hook for modules to affect the services available to a user.</para>
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
- <varlistentry>
|
||
+ <varlistentry condition="with_vendordir">
|
||
<term><filename>%vendordir%/pam.d</filename></term>
|
||
<listitem>
|
||
<para>
|
||
the <emphasis remap='B'>Linux-PAM</emphasis> vendor configuration
|
||
directory. Files in <filename>/etc/pam.d</filename> and
|
||
<filename>/usr/lib/pam.d</filename> override files with the same
|
||
- name in this directory. Only available if Linux-PAM was compiled
|
||
- with vendordir enabled.
|
||
+ name in this directory.
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
diff --git a/examples/Makefile.am b/examples/Makefile.am
|
||
index 722ec686..c4c3c261 100644
|
||
--- a/examples/Makefile.am
|
||
+++ b/examples/Makefile.am
|
||
@@ -11,4 +11,4 @@ AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||
LDADD = $(top_builddir)/libpam/libpam.la \
|
||
$(top_builddir)/libpam_misc/libpam_misc.la
|
||
|
||
-noinst_PROGRAMS = xsh vpass blank check_user
|
||
+noinst_PROGRAMS = xsh vpass blank check_user tty_conv
|
||
diff --git a/examples/tty_conv.c b/examples/tty_conv.c
|
||
new file mode 100644
|
||
index 00000000..23f0684c
|
||
--- /dev/null
|
||
+++ b/examples/tty_conv.c
|
||
@@ -0,0 +1,177 @@
|
||
+/* PlanC (hubenchang0515@outlook.com) -- an example application
|
||
+ * that implements a custom conversation */
|
||
+
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <errno.h>
|
||
+#include <unistd.h>
|
||
+#include <termio.h>
|
||
+#include <security/pam_appl.h>
|
||
+
|
||
+/***************************************
|
||
+ * @brief echo off/on
|
||
+ * @param[in] fd file descriptor
|
||
+ * @param[in] off 1 - echo off,0 - echo on
|
||
+ ***************************************/
|
||
+static void echoOff(int fd, int off)
|
||
+{
|
||
+ struct termio tty;
|
||
+ if (ioctl(fd, TCGETA, &tty) < 0)
|
||
+ {
|
||
+ fprintf(stderr, "TCGETA failed: %s\n", strerror(errno));
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if (off)
|
||
+ {
|
||
+ tty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
||
+ if (ioctl(fd, TCSETAF, &tty) < 0)
|
||
+ {
|
||
+ fprintf(stderr, "TCSETAF failed: %s\n", strerror(errno));
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ tty.c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL);
|
||
+ if (ioctl(fd, TCSETAW, &tty) < 0)
|
||
+ {
|
||
+ fprintf(stderr, "TCSETAW failed: %s\n", strerror(errno));
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/***************************************
|
||
+ * @brief echo off stdin
|
||
+ ***************************************/
|
||
+static void echoOffStdin(void)
|
||
+{
|
||
+ echoOff(fileno(stdin), 1);
|
||
+}
|
||
+
|
||
+/***************************************
|
||
+ * @brief echo on stdin
|
||
+ ***************************************/
|
||
+static void echoOnStdin(void)
|
||
+{
|
||
+ echoOff(fileno(stdin), 0);
|
||
+}
|
||
+
|
||
+/***************************************
|
||
+ * @brief read a line input
|
||
+ * @return the input string
|
||
+ ***************************************/
|
||
+static char *readline(void)
|
||
+{
|
||
+ char input[PAM_MAX_RESP_SIZE];
|
||
+ int i;
|
||
+
|
||
+ flockfile(stdin);
|
||
+ for (i = 0; i < PAM_MAX_RESP_SIZE; i++)
|
||
+ {
|
||
+ int ch = getchar_unlocked();
|
||
+ if (ch == '\n' || ch == '\r' ||ch == EOF)
|
||
+ break;
|
||
+ input[i] = ch;
|
||
+ }
|
||
+ funlockfile(stdin);
|
||
+ input[i] = '\0';
|
||
+
|
||
+ return (strdup(input));
|
||
+}
|
||
+
|
||
+/**************************************************
|
||
+ * @brief callback of PAM conversation
|
||
+ * @param[in] num_msg the count of message
|
||
+ * @param[in] msg PAM message
|
||
+ * @param[out] resp our response
|
||
+ * @param[in] appdata_ptr custom data passed by struct pam_conv.appdata_ptr
|
||
+ * @return state
|
||
+ **************************************************/
|
||
+static int conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
|
||
+{
|
||
+ (void)(appdata_ptr);
|
||
+ int i;
|
||
+
|
||
+ /* check the count of message */
|
||
+ if (num_msg <= 0 || num_msg >= PAM_MAX_MSG_SIZE)
|
||
+ {
|
||
+ fprintf(stderr, "invalid num_msg(%d)\n", num_msg);
|
||
+ return PAM_CONV_ERR;
|
||
+ }
|
||
+
|
||
+ /* alloc memory for response */
|
||
+ if ((resp[0] = malloc(num_msg * sizeof(struct pam_response))) == NULL)
|
||
+ {
|
||
+ fprintf(stderr, "bad alloc\n");
|
||
+ return PAM_BUF_ERR;
|
||
+ }
|
||
+
|
||
+ /* response for message */
|
||
+ for (i = 0; i < num_msg; i++)
|
||
+ {
|
||
+ const struct pam_message *m = *msg + i;
|
||
+ struct pam_response *r = *resp + i;
|
||
+ r->resp_retcode = 0; /* currently un-used, zero expected */
|
||
+ switch (m->msg_style)
|
||
+ {
|
||
+ case PAM_PROMPT_ECHO_OFF: /* get the input with echo off, like the password */
|
||
+ printf("%s", m->msg);
|
||
+ echoOffStdin();
|
||
+ r->resp = readline();
|
||
+ echoOnStdin();
|
||
+ printf("\n");
|
||
+ break;
|
||
+
|
||
+ case PAM_PROMPT_ECHO_ON: /* get the input with echo on, like the username */
|
||
+ printf("%s", m->msg);
|
||
+ r->resp = readline();
|
||
+ break;
|
||
+
|
||
+ case PAM_TEXT_INFO: /* normal info */
|
||
+ printf("%s\n", m->msg);
|
||
+ break;
|
||
+
|
||
+ case PAM_ERROR_MSG: /* error info */
|
||
+ fprintf(stderr, "%s\n", m->msg);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ fprintf(stderr, "unexpected msg_style: %d\n", m->msg_style);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ return PAM_SUCCESS;
|
||
+}
|
||
+
|
||
+int main(void)
|
||
+{
|
||
+ struct pam_conv pam_conv = {conversation, NULL};
|
||
+ pam_handle_t *pamh;
|
||
+
|
||
+ /* echo on while exist, like Ctrl+C on input password */
|
||
+ atexit(echoOnStdin);
|
||
+
|
||
+ if (PAM_SUCCESS != pam_start("login", NULL, &pam_conv, &pamh))
|
||
+ {
|
||
+ fprintf(stderr, "pam_start failed\n");
|
||
+ return EXIT_FAILURE;
|
||
+ }
|
||
+
|
||
+ if (PAM_SUCCESS != pam_authenticate(pamh, 0))
|
||
+ {
|
||
+ fprintf(stderr, "pam_authenticate failed\n");
|
||
+ pam_end(pamh, 0);
|
||
+ return EXIT_FAILURE;
|
||
+ }
|
||
+
|
||
+ if (PAM_SUCCESS != pam_acct_mgmt(pamh, 0))
|
||
+ {
|
||
+ fprintf(stderr, "pam_acct_mgmt failed\n");
|
||
+ pam_end(pamh, 0);
|
||
+ return EXIT_FAILURE;
|
||
+ }
|
||
+
|
||
+ pam_end(pamh, 0);
|
||
+ return EXIT_SUCCESS;
|
||
+}
|
||
diff --git a/examples/xsh.c b/examples/xsh.c
|
||
index ef4dca0c..5b34fc17 100644
|
||
--- a/examples/xsh.c
|
||
+++ b/examples/xsh.c
|
||
@@ -80,7 +80,7 @@ int main(int argc, char **argv)
|
||
tty = ttyname(fileno(stdin));
|
||
if (tty) {
|
||
retcode = pam_set_item(pamh, PAM_TTY, tty);
|
||
- bail_out(pamh,1,retcode,"pam_set_item(PAM_RHOST)");
|
||
+ bail_out(pamh,1,retcode,"pam_set_item(PAM_TTY)");
|
||
}
|
||
}
|
||
|
||
diff --git a/libpam/Makefile.am b/libpam/Makefile.am
|
||
index 55222afc..389d5d02 100644
|
||
--- a/libpam/Makefile.am
|
||
+++ b/libpam/Makefile.am
|
||
@@ -21,7 +21,7 @@ noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \
|
||
include/pam_inline.h include/test_assert.h
|
||
|
||
libpam_la_LDFLAGS = -no-undefined -version-info 85:1:85
|
||
-libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) $(ECONF_LIBS) @LIBDL@
|
||
+libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) $(ECONF_LIBS) @LIBDL@ @LTLIBINTL@
|
||
|
||
if HAVE_VERSIONING
|
||
libpam_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libpam.map
|
||
diff --git a/modules/pam_access/Makefile.am b/modules/pam_access/Makefile.am
|
||
index 5723dd59..b9fbefdb 100644
|
||
--- a/modules/pam_access/Makefile.am
|
||
+++ b/modules/pam_access/Makefile.am
|
||
@@ -18,8 +18,7 @@ securelibdir = $(SECUREDIR)
|
||
secureconfdir = $(SCONFIGDIR)
|
||
|
||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||
- -DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\" \
|
||
- -DACCESS_CONF_GLOB=\"$(SCONFIGDIR)/access.d/*.conf\" $(WARN_CFLAGS)
|
||
+ $(WARN_CFLAGS)
|
||
AM_LDFLAGS = -no-undefined -avoid-version -module
|
||
if HAVE_VERSIONING
|
||
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
|
||
index 277192b9..0d033aa2 100644
|
||
--- a/modules/pam_access/pam_access.c
|
||
+++ b/modules/pam_access/pam_access.c
|
||
@@ -56,6 +56,9 @@
|
||
#include "pam_cc_compat.h"
|
||
#include "pam_inline.h"
|
||
|
||
+#define PAM_ACCESS_CONFIG (SCONFIGDIR "/access.conf")
|
||
+#define ACCESS_CONF_GLOB (SCONFIGDIR "/access.d/*.conf")
|
||
+
|
||
/* login_access.c from logdaemon-5.6 with several changes by A.Nogin: */
|
||
|
||
/*
|
||
diff --git a/modules/pam_env/Makefile.am b/modules/pam_env/Makefile.am
|
||
index c66112d6..beca8e1a 100644
|
||
--- a/modules/pam_env/Makefile.am
|
||
+++ b/modules/pam_env/Makefile.am
|
||
@@ -18,7 +18,7 @@ securelibdir = $(SECUREDIR)
|
||
secureconfdir = $(SCONFIGDIR)
|
||
|
||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||
- -DDEFAULT_CONF_FILE=\"$(SCONFIGDIR)/pam_env.conf\" $(WARN_CFLAGS)
|
||
+ $(WARN_CFLAGS)
|
||
AM_LDFLAGS = -no-undefined -avoid-version -module
|
||
if HAVE_VERSIONING
|
||
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||
diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c
|
||
index f5f8cead..c03ec3a3 100644
|
||
--- a/modules/pam_env/pam_env.c
|
||
+++ b/modules/pam_env/pam_env.c
|
||
@@ -41,6 +41,8 @@ typedef struct var {
|
||
char *override;
|
||
} VAR;
|
||
|
||
+#define DEFAULT_CONF_FILE (SCONFIGDIR "/pam_env.conf")
|
||
+
|
||
#define BUF_SIZE 8192
|
||
#define MAX_ENV 8192
|
||
|
||
diff --git a/modules/pam_faillock/Makefile.am b/modules/pam_faillock/Makefile.am
|
||
index 44a49660..16d9f8bc 100644
|
||
--- a/modules/pam_faillock/Makefile.am
|
||
+++ b/modules/pam_faillock/Makefile.am
|
||
@@ -15,7 +15,7 @@ endif
|
||
XMLS = README.xml pam_faillock.8.xml faillock.8.xml faillock.conf.5.xml
|
||
|
||
dist_check_SCRIPTS = tst-pam_faillock
|
||
-TESTS = $(dist_check_SCRIPTS)
|
||
+TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS)
|
||
|
||
securelibdir = $(SECUREDIR)
|
||
secureconfdir = $(SCONFIGDIR)
|
||
@@ -33,6 +33,9 @@ if HAVE_VERSIONING
|
||
pam_faillock_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||
endif
|
||
|
||
+check_PROGRAMS = tst-pam_faillock-retval
|
||
+tst_pam_faillock_retval_LDADD = $(top_builddir)/libpam/libpam.la
|
||
+
|
||
faillock_LDFLAGS = @EXE_LDFLAGS@
|
||
faillock_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT)
|
||
|
||
diff --git a/modules/pam_faillock/faillock.h b/modules/pam_faillock/faillock.h
|
||
index b22a9dfb..c3f157ef 100644
|
||
--- a/modules/pam_faillock/faillock.h
|
||
+++ b/modules/pam_faillock/faillock.h
|
||
@@ -67,7 +67,10 @@ struct tally_data {
|
||
};
|
||
|
||
#define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock"
|
||
-#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf"
|
||
+#define FAILLOCK_DEFAULT_CONF SCONFIGDIR "/faillock.conf"
|
||
+#ifdef VENDOR_SCONFIGDIR
|
||
+#define VENDOR_FAILLOCK_DEFAULT_CONF VENDOR_SCONFIGDIR "/faillock.conf"
|
||
+#endif
|
||
|
||
int open_tally(const char *dir, const char *user, uid_t uid, int create);
|
||
int read_tally(int fd, struct tally_data *tallies);
|
||
diff --git a/modules/pam_faillock/main.c b/modules/pam_faillock/main.c
|
||
index f62e1bb2..ea6329ca 100644
|
||
--- a/modules/pam_faillock/main.c
|
||
+++ b/modules/pam_faillock/main.c
|
||
@@ -174,6 +174,11 @@ do_user(struct options *opts, const char *user)
|
||
time_t when = tallies.records[i].time;
|
||
|
||
tm = localtime(&when);
|
||
+ if(tm == NULL) {
|
||
+ fprintf(stderr, "%s: Invalid timestamp in the tally record\n",
|
||
+ opts->progname);
|
||
+ continue;
|
||
+ }
|
||
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm);
|
||
printf("%-19s %-5s %-52.52s %s\n", timebuf,
|
||
status & TALLY_STATUS_RHOST ? "RHOST" : (status & TALLY_STATUS_TTY ? "TTY" : "SVC"),
|
||
diff --git a/modules/pam_faillock/pam_faillock.8.xml b/modules/pam_faillock/pam_faillock.8.xml
|
||
index 58c16442..79bcbbd0 100644
|
||
--- a/modules/pam_faillock/pam_faillock.8.xml
|
||
+++ b/modules/pam_faillock/pam_faillock.8.xml
|
||
@@ -134,10 +134,17 @@
|
||
<option>conf=/path/to/config-file</option>
|
||
</term>
|
||
<listitem>
|
||
- <para>
|
||
+ <para condition="without_vendordir">
|
||
Use another configuration file instead of the default
|
||
<filename>/etc/security/faillock.conf</filename>.
|
||
</para>
|
||
+ <para condition="with_vendordir">
|
||
+ Use another configuration file instead of the default
|
||
+ which is to use the file
|
||
+ <filename>/etc/security/faillock.conf</filename> or,
|
||
+ if that one is not present, the file
|
||
+ <filename>%vendordir%/security/faillock.conf</filename>.
|
||
+ </para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
@@ -328,6 +335,15 @@ session required pam_selinux.so open
|
||
<para>the config file for pam_faillock options</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
+ <varlistentry condition="with_vendordir">
|
||
+ <term><filename>%vendordir%/security/faillock.conf</filename></term>
|
||
+ <listitem>
|
||
+ <para>
|
||
+ the config file for pam_faillock options. It will be used if
|
||
+ <filename>/etc/security/faillock.conf</filename> does not exist.
|
||
+ </para>
|
||
+ </listitem>
|
||
+ </varlistentry>
|
||
</variablelist>
|
||
</refsect1>
|
||
|
||
diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c
|
||
index 8328fbae..932d4281 100644
|
||
--- a/modules/pam_faillock/pam_faillock.c
|
||
+++ b/modules/pam_faillock/pam_faillock.c
|
||
@@ -192,6 +192,15 @@ read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile)
|
||
char linebuf[FAILLOCK_CONF_MAX_LINELEN+1];
|
||
|
||
f = fopen(cfgfile, "r");
|
||
+#ifdef VENDOR_FAILLOCK_DEFAULT_CONF
|
||
+ if (f == NULL && errno == ENOENT && cfgfile == default_faillock_conf) {
|
||
+ /*
|
||
+ * If the default configuration file in /etc does not exist,
|
||
+ * try the vendor configuration file as fallback.
|
||
+ */
|
||
+ f = fopen(VENDOR_FAILLOCK_DEFAULT_CONF, "r");
|
||
+ }
|
||
+#endif
|
||
if (f == NULL) {
|
||
/* ignore non-existent default config file */
|
||
if (errno == ENOENT && cfgfile == default_faillock_conf)
|
||
diff --git a/modules/pam_faillock/tst-pam_faillock-retval.c b/modules/pam_faillock/tst-pam_faillock-retval.c
|
||
new file mode 100644
|
||
index 00000000..133026cb
|
||
--- /dev/null
|
||
+++ b/modules/pam_faillock/tst-pam_faillock-retval.c
|
||
@@ -0,0 +1,119 @@
|
||
+/*
|
||
+ * Check pam_faillock return values.
|
||
+ */
|
||
+
|
||
+#include "test_assert.h"
|
||
+
|
||
+#include <limits.h>
|
||
+#include <stdio.h>
|
||
+#include <string.h>
|
||
+#include <unistd.h>
|
||
+#include <security/pam_appl.h>
|
||
+
|
||
+#define MODULE_NAME "pam_faillock"
|
||
+#define TEST_NAME "tst-" MODULE_NAME "-retval"
|
||
+
|
||
+static const char service_file[] = TEST_NAME ".service";
|
||
+static const char config_filename[] = TEST_NAME ".conf";
|
||
+static const char user_name[] = "root";
|
||
+static struct pam_conv conv;
|
||
+
|
||
+int
|
||
+main(void)
|
||
+{
|
||
+ pam_handle_t *pamh = NULL;
|
||
+ FILE *fp;
|
||
+ char cwd[PATH_MAX];
|
||
+
|
||
+ ASSERT_NE(NULL, getcwd(cwd, sizeof(cwd)));
|
||
+
|
||
+ ASSERT_NE(NULL, fp = fopen(config_filename, "w"));
|
||
+ ASSERT_LT(0, fprintf(fp,
|
||
+ "deny = 2\n"
|
||
+ "unlock_time = 5\n"
|
||
+ "root_unlock_time = 5\n"));
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ /* root has access */
|
||
+ ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||
+ ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||
+ "auth required %s/../pam_permit/.libs/pam_permit.so\n"
|
||
+ "auth required %s/.libs/%s.so authsucc even_deny_root dir=%s conf=%s\n"
|
||
+ "account required %s/.libs/%s.so dir=%s\n"
|
||
+ "password required %s/.libs/%s.so dir=%s\n"
|
||
+ "session required %s/.libs/%s.so dir=%s\n",
|
||
+ cwd,
|
||
+ cwd, MODULE_NAME, cwd, config_filename,
|
||
+ cwd, MODULE_NAME, cwd,
|
||
+ cwd, MODULE_NAME, cwd,
|
||
+ cwd, MODULE_NAME, cwd));
|
||
+
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ ASSERT_EQ(PAM_SUCCESS,
|
||
+ pam_start_confdir(service_file, user_name, &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_SUCCESS, pam_acct_mgmt(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_chauthtok(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_open_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_close_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||
+ ASSERT_EQ(0, unlink(service_file));
|
||
+ pamh = NULL;
|
||
+
|
||
+ /* root tries to login 2 times without success*/
|
||
+ ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||
+ ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||
+ "auth requisite %s/.libs/%s.so dir=%s preauth even_deny_root conf=%s\n"
|
||
+ "auth [success=1 default=bad] %s/../pam_debug/.libs/pam_debug.so auth=perm_denied cred=success\n"
|
||
+ "auth [default=die] %s/.libs/%s.so dir=%s authfail even_deny_root conf=%s\n"
|
||
+ "auth sufficient %s/.libs/%s.so dir=%s authsucc even_deny_root conf=%s\n",
|
||
+ cwd, MODULE_NAME, cwd, config_filename,
|
||
+ cwd,
|
||
+ cwd, MODULE_NAME, cwd, config_filename,
|
||
+ cwd, MODULE_NAME, cwd, config_filename));
|
||
+
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ ASSERT_EQ(PAM_SUCCESS,
|
||
+ pam_start_confdir(service_file, user_name, &conv, ".", &pamh));
|
||
+ ASSERT_NE(NULL, pamh);
|
||
+ ASSERT_EQ(PAM_PERM_DENIED, pam_authenticate(pamh, 0));
|
||
+ ASSERT_EQ(PAM_PERM_DENIED, pam_authenticate(pamh, 0));
|
||
+ pamh = NULL;
|
||
+ ASSERT_EQ(0, unlink(service_file));
|
||
+
|
||
+ /* root is locked for 5 sec*/
|
||
+ ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||
+ ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
||
+ "auth requisite %s/.libs/%s.so dir=%s preauth even_deny_root conf=%s\n"
|
||
+ "auth [success=1 default=bad] %s/../pam_debug/.libs/pam_debug.so auth=success cred=success\n"
|
||
+ "auth [default=die] %s/.libs/%s.so dir=%s authfail even_deny_root conf=%s\n"
|
||
+ "auth sufficient %s/.libs/%s.so dir=%s authsucc even_deny_root conf=%s\n",
|
||
+ cwd, MODULE_NAME, cwd, config_filename,
|
||
+ cwd,
|
||
+ cwd, MODULE_NAME, cwd, config_filename,
|
||
+ cwd, MODULE_NAME, cwd, config_filename));
|
||
+
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ ASSERT_EQ(PAM_SUCCESS,
|
||
+ pam_start_confdir(service_file, user_name, &conv, ".", &pamh));
|
||
+ ASSERT_NE(NULL, pamh);
|
||
+ ASSERT_EQ(PAM_AUTH_ERR, pam_authenticate(pamh, 0));
|
||
+
|
||
+ /* waiting at least 5 sec --> login is working again*/
|
||
+ sleep(6);
|
||
+ ASSERT_EQ(PAM_SUCCESS, pam_authenticate(pamh, 0));
|
||
+
|
||
+ ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||
+ ASSERT_EQ(0, unlink(service_file));
|
||
+ pamh = NULL;
|
||
+
|
||
+ ASSERT_EQ(0,unlink(user_name));
|
||
+ ASSERT_EQ(0,unlink(config_filename));
|
||
+
|
||
+ return 0;
|
||
+}
|
||
diff --git a/modules/pam_group/Makefile.am b/modules/pam_group/Makefile.am
|
||
index a9a0a1ef..fd88b952 100644
|
||
--- a/modules/pam_group/Makefile.am
|
||
+++ b/modules/pam_group/Makefile.am
|
||
@@ -18,7 +18,7 @@ securelibdir = $(SECUREDIR)
|
||
secureconfdir = $(SCONFIGDIR)
|
||
|
||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||
- -DPAM_GROUP_CONF=\"$(SCONFIGDIR)/group.conf\" $(WARN_CFLAGS)
|
||
+ $(WARN_CFLAGS)
|
||
AM_LDFLAGS = -no-undefined -avoid-version -module
|
||
if HAVE_VERSIONING
|
||
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||
diff --git a/modules/pam_group/pam_group.8.xml b/modules/pam_group/pam_group.8.xml
|
||
index 2c1c9058..e4a59dfd 100644
|
||
--- a/modules/pam_group/pam_group.8.xml
|
||
+++ b/modules/pam_group/pam_group.8.xml
|
||
@@ -38,6 +38,10 @@
|
||
By default rules for group memberships are taken from config file
|
||
<filename>/etc/security/group.conf</filename>.
|
||
</para>
|
||
+ <para condition="with_vendordir">
|
||
+ If <filename>/etc/security/group.conf</filename> does not exist,
|
||
+ <filename>%vendordir%/security/group.conf</filename> is used.
|
||
+ </para>
|
||
<para>
|
||
This module's usefulness relies on the file-systems
|
||
accessible to the user. The point being that once granted the
|
||
diff --git a/modules/pam_group/pam_group.c b/modules/pam_group/pam_group.c
|
||
index d9a35ea6..c49358a1 100644
|
||
--- a/modules/pam_group/pam_group.c
|
||
+++ b/modules/pam_group/pam_group.c
|
||
@@ -16,6 +16,7 @@
|
||
#include <time.h>
|
||
#include <syslog.h>
|
||
#include <string.h>
|
||
+#include <errno.h>
|
||
|
||
#include <grp.h>
|
||
#include <sys/types.h>
|
||
@@ -23,6 +24,10 @@
|
||
#include <fcntl.h>
|
||
#include <netdb.h>
|
||
|
||
+#define PAM_GROUP_CONF SCONFIGDIR "/group.conf"
|
||
+#ifdef VENDOR_SCONFIGDIR
|
||
+# define VENDOR_PAM_GROUP_CONF VENDOR_SCONFIGDIR "/group.conf"
|
||
+#endif
|
||
#define PAM_GROUP_BUFLEN 1000
|
||
#define FIELD_SEPARATOR ';' /* this is new as of .02 */
|
||
|
||
@@ -70,7 +75,8 @@ trim_spaces(char *buf, char *from)
|
||
#define STATE_EOF 3 /* end of file or error */
|
||
|
||
static int
|
||
-read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state)
|
||
+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state,
|
||
+ const char *conf_filename)
|
||
{
|
||
char *to;
|
||
char *src;
|
||
@@ -89,9 +95,9 @@ read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state)
|
||
}
|
||
*from = 0;
|
||
*state = STATE_NL;
|
||
- fd = open(PAM_GROUP_CONF, O_RDONLY);
|
||
+ fd = open(conf_filename, O_RDONLY);
|
||
if (fd < 0) {
|
||
- pam_syslog(pamh, LOG_ERR, "error opening %s: %m", PAM_GROUP_CONF);
|
||
+ pam_syslog(pamh, LOG_ERR, "error opening %s: %m", conf_filename);
|
||
_pam_drop(*buf);
|
||
*state = STATE_EOF;
|
||
return -1;
|
||
@@ -106,7 +112,7 @@ read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state)
|
||
while (fd != -1 && to - *buf < PAM_GROUP_BUFLEN) {
|
||
i = pam_modutil_read(fd, to, PAM_GROUP_BUFLEN - (to - *buf));
|
||
if (i < 0) {
|
||
- pam_syslog(pamh, LOG_ERR, "error reading %s: %m", PAM_GROUP_CONF);
|
||
+ pam_syslog(pamh, LOG_ERR, "error reading %s: %m", conf_filename);
|
||
close(fd);
|
||
memset(*buf, 0, PAM_GROUP_BUFLEN);
|
||
_pam_drop(*buf);
|
||
@@ -573,6 +579,18 @@ static int check_account(pam_handle_t *pamh, const char *service,
|
||
int retval=PAM_SUCCESS;
|
||
gid_t *grps;
|
||
int no_grps;
|
||
+ const char *conf_filename = PAM_GROUP_CONF;
|
||
+
|
||
+#ifdef VENDOR_PAM_GROUP_CONF
|
||
+ /*
|
||
+ * Check whether PAM_GROUP_CONF file is available.
|
||
+ * If it does not exist, fall back to VENDOR_PAM_GROUP_CONF file.
|
||
+ */
|
||
+ struct stat stat_buffer;
|
||
+ if (stat(conf_filename, &stat_buffer) != 0 && errno == ENOENT) {
|
||
+ conf_filename = VENDOR_PAM_GROUP_CONF;
|
||
+ }
|
||
+#endif
|
||
|
||
/*
|
||
* first we get the current list of groups - the application
|
||
@@ -611,7 +629,7 @@ static int check_account(pam_handle_t *pamh, const char *service,
|
||
|
||
/* here we get the service name field */
|
||
|
||
- fd = read_field(pamh, fd, &buffer, &from, &state);
|
||
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
|
||
if (!buffer || !buffer[0]) {
|
||
/* empty line .. ? */
|
||
continue;
|
||
@@ -621,7 +639,7 @@ static int check_account(pam_handle_t *pamh, const char *service,
|
||
|
||
if (state != STATE_FIELD) {
|
||
pam_syslog(pamh, LOG_ERR,
|
||
- "%s: malformed rule #%d", PAM_GROUP_CONF, count);
|
||
+ "%s: malformed rule #%d", conf_filename, count);
|
||
continue;
|
||
}
|
||
|
||
@@ -630,10 +648,10 @@ static int check_account(pam_handle_t *pamh, const char *service,
|
||
|
||
/* here we get the terminal name field */
|
||
|
||
- fd = read_field(pamh, fd, &buffer, &from, &state);
|
||
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
|
||
if (state != STATE_FIELD) {
|
||
pam_syslog(pamh, LOG_ERR,
|
||
- "%s: malformed rule #%d", PAM_GROUP_CONF, count);
|
||
+ "%s: malformed rule #%d", conf_filename, count);
|
||
continue;
|
||
}
|
||
good &= logic_field(pamh,tty, buffer, count, is_same);
|
||
@@ -641,10 +659,10 @@ static int check_account(pam_handle_t *pamh, const char *service,
|
||
|
||
/* here we get the username field */
|
||
|
||
- fd = read_field(pamh, fd, &buffer, &from, &state);
|
||
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
|
||
if (state != STATE_FIELD) {
|
||
pam_syslog(pamh, LOG_ERR,
|
||
- "%s: malformed rule #%d", PAM_GROUP_CONF, count);
|
||
+ "%s: malformed rule #%d", conf_filename, count);
|
||
continue;
|
||
}
|
||
/* If buffer starts with @, we are using netgroups */
|
||
@@ -663,20 +681,20 @@ static int check_account(pam_handle_t *pamh, const char *service,
|
||
|
||
/* here we get the time field */
|
||
|
||
- fd = read_field(pamh, fd, &buffer, &from, &state);
|
||
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
|
||
if (state != STATE_FIELD) {
|
||
pam_syslog(pamh, LOG_ERR,
|
||
- "%s: malformed rule #%d", PAM_GROUP_CONF, count);
|
||
+ "%s: malformed rule #%d", conf_filename, count);
|
||
continue;
|
||
}
|
||
|
||
good &= logic_field(pamh,&here_and_now, buffer, count, check_time);
|
||
D(("with time: %s", good ? "passes":"fails" ));
|
||
|
||
- fd = read_field(pamh, fd, &buffer, &from, &state);
|
||
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
|
||
if (state == STATE_FIELD) {
|
||
pam_syslog(pamh, LOG_ERR,
|
||
- "%s: poorly terminated rule #%d", PAM_GROUP_CONF, count);
|
||
+ "%s: poorly terminated rule #%d", conf_filename, count);
|
||
continue;
|
||
}
|
||
|
||
diff --git a/modules/pam_limits/Makefile.am b/modules/pam_limits/Makefile.am
|
||
index 911b07b3..9ae1794d 100644
|
||
--- a/modules/pam_limits/Makefile.am
|
||
+++ b/modules/pam_limits/Makefile.am
|
||
@@ -19,8 +19,8 @@ secureconfdir = $(SCONFIGDIR)
|
||
limits_conf_dir = $(SCONFIGDIR)/limits.d
|
||
|
||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||
- -DLIMITS_FILE_DIR=\"$(limits_conf_dir)/*.conf\" \
|
||
- -DLIMITS_FILE=\"$(SCONFIGDIR)/limits.conf\" $(WARN_CFLAGS)
|
||
+ -DLIMITS_FILE_DIR=\"$(limits_conf_dir)\" \
|
||
+ $(WARN_CFLAGS)
|
||
AM_LDFLAGS = -no-undefined -avoid-version -module
|
||
if HAVE_VERSIONING
|
||
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||
diff --git a/modules/pam_limits/pam_limits.8.xml b/modules/pam_limits/pam_limits.8.xml
|
||
index bc46cbf4..08c6fc4d 100644
|
||
--- a/modules/pam_limits/pam_limits.8.xml
|
||
+++ b/modules/pam_limits/pam_limits.8.xml
|
||
@@ -57,6 +57,11 @@
|
||
If a config file is explicitly specified with a module option then the
|
||
files in the above directory are not parsed.
|
||
</para>
|
||
+ <para condition="with_vendordir">
|
||
+ If there is no explicitly specified configuration file and
|
||
+ <filename>/etc/security/limits.conf</filename> does not exist,
|
||
+ <filename>%vendordir%/security/limits.conf</filename> is used.
|
||
+ </para>
|
||
<para>
|
||
The module must not be called by a multithreaded application.
|
||
</para>
|
||
diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c
|
||
index 7cc45d77..6fbe95fc 100644
|
||
--- a/modules/pam_limits/pam_limits.c
|
||
+++ b/modules/pam_limits/pam_limits.c
|
||
@@ -47,6 +47,10 @@
|
||
#include <libaudit.h>
|
||
#endif
|
||
|
||
+#ifndef PR_SET_NO_NEW_PRIVS
|
||
+# define PR_SET_NO_NEW_PRIVS 38 /* from <linux/prctl.h> */
|
||
+#endif
|
||
+
|
||
/* Module defines */
|
||
#define LINE_LENGTH 1024
|
||
|
||
@@ -119,9 +123,10 @@ struct pam_limit_s {
|
||
#define PAM_SET_ALL 0x0010
|
||
|
||
/* Limits from globbed files. */
|
||
-#define LIMITS_CONF_GLOB LIMITS_FILE_DIR
|
||
+#define LIMITS_CONF_GLOB (LIMITS_FILE_DIR "/*.conf")
|
||
|
||
-#define CONF_FILE (pl->conf_file != NULL)?pl->conf_file:LIMITS_FILE
|
||
+#define LIMITS_FILE (SCONFIGDIR "/limits.conf")
|
||
+#define CONF_FILE ((pl->conf_file != NULL) ? pl->conf_file : LIMITS_FILE)
|
||
|
||
static int
|
||
_pam_parse (const pam_handle_t *pamh, int argc, const char **argv,
|
||
@@ -811,14 +816,30 @@ parse_config_file(pam_handle_t *pamh, const char *uname, uid_t uid, gid_t gid,
|
||
FILE *fil;
|
||
char buf[LINE_LENGTH];
|
||
|
||
- /* check for the LIMITS_FILE */
|
||
+ /* check for the CONF_FILE */
|
||
if (ctrl & PAM_DEBUG_ARG)
|
||
pam_syslog(pamh, LOG_DEBUG, "reading settings from '%s'", CONF_FILE);
|
||
fil = fopen(CONF_FILE, "r");
|
||
if (fil == NULL) {
|
||
- pam_syslog (pamh, LOG_WARNING,
|
||
- "cannot read settings from %s: %m", CONF_FILE);
|
||
- return PAM_SERVICE_ERR;
|
||
+ int err = errno;
|
||
+
|
||
+#ifdef VENDOR_SCONFIGDIR
|
||
+ /* if the specified file does not exist, and it is not provided by
|
||
+ the user, try the vendor file as fallback. */
|
||
+ if (pl->conf_file == NULL && err == ENOENT)
|
||
+ fil = fopen(VENDOR_SCONFIGDIR "/limits.conf", "r");
|
||
+
|
||
+ if (fil == NULL)
|
||
+#endif
|
||
+ {
|
||
+ if (err == ENOENT)
|
||
+ return PAM_SUCCESS;
|
||
+
|
||
+ pam_syslog (pamh, LOG_WARNING,
|
||
+ "cannot read settings from %s: %s", CONF_FILE,
|
||
+ strerror(err));
|
||
+ return PAM_SERVICE_ERR;
|
||
+ }
|
||
}
|
||
|
||
/* start the show */
|
||
diff --git a/modules/pam_namespace/Makefile.am b/modules/pam_namespace/Makefile.am
|
||
index 47cc38e1..33375857 100644
|
||
--- a/modules/pam_namespace/Makefile.am
|
||
+++ b/modules/pam_namespace/Makefile.am
|
||
@@ -21,7 +21,7 @@ namespaceddir = $(SCONFIGDIR)/namespace.d
|
||
servicedir = $(systemdunitdir)
|
||
|
||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||
- -DSECURECONF_DIR=\"$(SCONFIGDIR)/\" $(WARN_CFLAGS)
|
||
+ $(WARN_CFLAGS)
|
||
AM_LDFLAGS = -no-undefined -avoid-version -module
|
||
if HAVE_VERSIONING
|
||
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||
diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h
|
||
index b51f2841..169bd59f 100644
|
||
--- a/modules/pam_namespace/pam_namespace.h
|
||
+++ b/modules/pam_namespace/pam_namespace.h
|
||
@@ -90,14 +90,10 @@
|
||
/*
|
||
* Module defines
|
||
*/
|
||
-#ifndef SECURECONF_DIR
|
||
-#define SECURECONF_DIR "/etc/security/"
|
||
-#endif
|
||
-
|
||
-#define PAM_NAMESPACE_CONFIG (SECURECONF_DIR "namespace.conf")
|
||
-#define NAMESPACE_INIT_SCRIPT (SECURECONF_DIR "namespace.init")
|
||
-#define NAMESPACE_D_DIR (SECURECONF_DIR "namespace.d/")
|
||
-#define NAMESPACE_D_GLOB (SECURECONF_DIR "namespace.d/*.conf")
|
||
+#define PAM_NAMESPACE_CONFIG (SCONFIGDIR "/namespace.conf")
|
||
+#define NAMESPACE_INIT_SCRIPT (SCONFIGDIR "/namespace.init")
|
||
+#define NAMESPACE_D_DIR (SCONFIGDIR "/namespace.d/")
|
||
+#define NAMESPACE_D_GLOB (SCONFIGDIR "/namespace.d/*.conf")
|
||
|
||
/* module flags */
|
||
#define PAMNS_DEBUG 0x00000100 /* Running in debug mode */
|
||
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
|
||
index a6cd3d2a..1d3242ca 100644
|
||
--- a/modules/pam_pwhistory/opasswd.c
|
||
+++ b/modules/pam_pwhistory/opasswd.c
|
||
@@ -44,6 +44,7 @@
|
||
#include <ctype.h>
|
||
#include <errno.h>
|
||
#include <fcntl.h>
|
||
+#include <limits.h>
|
||
#include <stdio.h>
|
||
#include <unistd.h>
|
||
#include <string.h>
|
||
@@ -74,8 +75,7 @@
|
||
#define RANDOM_DEVICE "/dev/urandom"
|
||
#endif
|
||
|
||
-#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
|
||
-#define TMP_PASSWORDS_FILE OLD_PASSWORDS_FILE".tmpXXXXXX"
|
||
+#define DEFAULT_OLD_PASSWORDS_FILE SCONFIGDIR "/opasswd"
|
||
|
||
#define DEFAULT_BUFLEN 4096
|
||
|
||
@@ -142,7 +142,7 @@ compare_password(const char *newpass, const char *oldpass)
|
||
|
||
/* Check, if the new password is already in the opasswd file. */
|
||
PAMH_ARG_DECL(int
|
||
-check_old_pass, const char *user, const char *newpass, int debug)
|
||
+check_old_pass, const char *user, const char *newpass, const char *filename, int debug)
|
||
{
|
||
int retval = PAM_SUCCESS;
|
||
FILE *oldpf;
|
||
@@ -156,10 +156,13 @@ check_old_pass, const char *user, const char *newpass, int debug)
|
||
return PAM_PWHISTORY_RUN_HELPER;
|
||
#endif
|
||
|
||
- if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL)
|
||
+ const char *opasswd_file =
|
||
+ (filename != NULL ? filename : DEFAULT_OLD_PASSWORDS_FILE);
|
||
+
|
||
+ if ((oldpf = fopen (opasswd_file, "r")) == NULL)
|
||
{
|
||
if (errno != ENOENT)
|
||
- pam_syslog (pamh, LOG_ERR, "Cannot open %s: %m", OLD_PASSWORDS_FILE);
|
||
+ pam_syslog (pamh, LOG_ERR, "Cannot open %s: %m", opasswd_file);
|
||
return PAM_SUCCESS;
|
||
}
|
||
|
||
@@ -242,9 +245,8 @@ check_old_pass, const char *user, const char *newpass, int debug)
|
||
}
|
||
|
||
PAMH_ARG_DECL(int
|
||
-save_old_pass, const char *user, int howmany, int debug UNUSED)
|
||
+save_old_pass, const char *user, int howmany, const char *filename, int debug UNUSED)
|
||
{
|
||
- char opasswd_tmp[] = TMP_PASSWORDS_FILE;
|
||
struct stat opasswd_stat;
|
||
FILE *oldpf, *newpf;
|
||
int newpf_fd;
|
||
@@ -256,6 +258,15 @@ save_old_pass, const char *user, int howmany, int debug UNUSED)
|
||
struct passwd *pwd;
|
||
const char *oldpass;
|
||
|
||
+ /* Define opasswd file and temp file for opasswd */
|
||
+ const char *opasswd_file =
|
||
+ (filename != NULL ? filename : DEFAULT_OLD_PASSWORDS_FILE);
|
||
+ char opasswd_tmp[PATH_MAX];
|
||
+
|
||
+ if ((size_t) snprintf (opasswd_tmp, sizeof (opasswd_tmp), "%s.tmpXXXXXX",
|
||
+ opasswd_file) >= sizeof (opasswd_tmp))
|
||
+ return PAM_BUF_ERR;
|
||
+
|
||
pwd = pam_modutil_getpwnam (pamh, user);
|
||
if (pwd == NULL)
|
||
return PAM_USER_UNKNOWN;
|
||
@@ -285,24 +296,22 @@ save_old_pass, const char *user, int howmany, int debug UNUSED)
|
||
if (oldpass == NULL || *oldpass == '\0')
|
||
return PAM_SUCCESS;
|
||
|
||
- if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL)
|
||
+ if ((oldpf = fopen (opasswd_file, "r")) == NULL)
|
||
{
|
||
if (errno == ENOENT)
|
||
{
|
||
- pam_syslog (pamh, LOG_NOTICE, "Creating %s",
|
||
- OLD_PASSWORDS_FILE);
|
||
+ pam_syslog (pamh, LOG_NOTICE, "Creating %s", opasswd_file);
|
||
do_create = 1;
|
||
}
|
||
else
|
||
{
|
||
- pam_syslog (pamh, LOG_ERR, "Cannot open %s: %m",
|
||
- OLD_PASSWORDS_FILE);
|
||
+ pam_syslog (pamh, LOG_ERR, "Cannot open %s: %m", opasswd_file);
|
||
return PAM_AUTHTOK_ERR;
|
||
}
|
||
}
|
||
else if (fstat (fileno (oldpf), &opasswd_stat) < 0)
|
||
{
|
||
- pam_syslog (pamh, LOG_ERR, "Cannot stat %s: %m", OLD_PASSWORDS_FILE);
|
||
+ pam_syslog (pamh, LOG_ERR, "Cannot stat %s: %m", opasswd_file);
|
||
fclose (oldpf);
|
||
return PAM_AUTHTOK_ERR;
|
||
}
|
||
@@ -312,7 +321,7 @@ save_old_pass, const char *user, int howmany, int debug UNUSED)
|
||
if (newpf_fd == -1)
|
||
{
|
||
pam_syslog (pamh, LOG_ERR, "Cannot create %s temp file: %m",
|
||
- OLD_PASSWORDS_FILE);
|
||
+ opasswd_file);
|
||
if (oldpf)
|
||
fclose (oldpf);
|
||
return PAM_AUTHTOK_ERR;
|
||
@@ -321,23 +330,19 @@ save_old_pass, const char *user, int howmany, int debug UNUSED)
|
||
{
|
||
if (fchmod (newpf_fd, S_IRUSR|S_IWUSR) != 0)
|
||
pam_syslog (pamh, LOG_ERR,
|
||
- "Cannot set permissions of %s temp file: %m",
|
||
- OLD_PASSWORDS_FILE);
|
||
+ "Cannot set permissions of %s temp file: %m", opasswd_file);
|
||
if (fchown (newpf_fd, 0, 0) != 0)
|
||
pam_syslog (pamh, LOG_ERR,
|
||
- "Cannot set owner/group of %s temp file: %m",
|
||
- OLD_PASSWORDS_FILE);
|
||
+ "Cannot set owner/group of %s temp file: %m", opasswd_file);
|
||
}
|
||
else
|
||
{
|
||
if (fchmod (newpf_fd, opasswd_stat.st_mode) != 0)
|
||
pam_syslog (pamh, LOG_ERR,
|
||
- "Cannot set permissions of %s temp file: %m",
|
||
- OLD_PASSWORDS_FILE);
|
||
+ "Cannot set permissions of %s temp file: %m", opasswd_file);
|
||
if (fchown (newpf_fd, opasswd_stat.st_uid, opasswd_stat.st_gid) != 0)
|
||
pam_syslog (pamh, LOG_ERR,
|
||
- "Cannot set owner/group of %s temp file: %m",
|
||
- OLD_PASSWORDS_FILE);
|
||
+ "Cannot set owner/group of %s temp file: %m", opasswd_file);
|
||
}
|
||
newpf = fdopen (newpf_fd, "w+");
|
||
if (newpf == NULL)
|
||
@@ -550,12 +555,20 @@ save_old_pass, const char *user, int howmany, int debug UNUSED)
|
||
goto error_opasswd;
|
||
}
|
||
|
||
- unlink (OLD_PASSWORDS_FILE".old");
|
||
- if (link (OLD_PASSWORDS_FILE, OLD_PASSWORDS_FILE".old") != 0 &&
|
||
+ char opasswd_backup[PATH_MAX];
|
||
+ if ((size_t) snprintf (opasswd_backup, sizeof (opasswd_backup), "%s.old",
|
||
+ opasswd_file) >= sizeof (opasswd_backup))
|
||
+ {
|
||
+ retval = PAM_BUF_ERR;
|
||
+ goto error_opasswd;
|
||
+ }
|
||
+
|
||
+ unlink (opasswd_backup);
|
||
+ if (link (opasswd_file, opasswd_backup) != 0 &&
|
||
errno != ENOENT)
|
||
pam_syslog (pamh, LOG_ERR, "Cannot create backup file of %s: %m",
|
||
- OLD_PASSWORDS_FILE);
|
||
- rename (opasswd_tmp, OLD_PASSWORDS_FILE);
|
||
+ opasswd_file);
|
||
+ rename (opasswd_tmp, opasswd_file);
|
||
error_opasswd:
|
||
unlink (opasswd_tmp);
|
||
free (buf);
|
||
diff --git a/modules/pam_pwhistory/opasswd.h b/modules/pam_pwhistory/opasswd.h
|
||
index 3f257288..19a4062c 100644
|
||
--- a/modules/pam_pwhistory/opasswd.h
|
||
+++ b/modules/pam_pwhistory/opasswd.h
|
||
@@ -57,10 +57,10 @@ void
|
||
helper_log_err(int err, const char *format, ...);
|
||
#endif
|
||
|
||
-PAMH_ARG_DECL(int
|
||
-check_old_pass, const char *user, const char *newpass, int debug);
|
||
+PAMH_ARG_DECL(int check_old_pass, const char *user, const char *newpass,
|
||
+ const char *filename, int debug);
|
||
|
||
-PAMH_ARG_DECL(int
|
||
-save_old_pass, const char *user, int howmany, int debug);
|
||
+PAMH_ARG_DECL(int save_old_pass, const char *user, int howmany,
|
||
+ const char *filename, int debug);
|
||
|
||
#endif /* __OPASSWD_H__ */
|
||
diff --git a/modules/pam_pwhistory/pam_pwhistory.8.xml b/modules/pam_pwhistory/pam_pwhistory.8.xml
|
||
index d88115c2..df16a776 100644
|
||
--- a/modules/pam_pwhistory/pam_pwhistory.8.xml
|
||
+++ b/modules/pam_pwhistory/pam_pwhistory.8.xml
|
||
@@ -36,6 +36,9 @@
|
||
<arg choice="opt">
|
||
authtok_type=<replaceable>STRING</replaceable>
|
||
</arg>
|
||
+ <arg choice="opt">
|
||
+ file=<replaceable>/path/filename</replaceable>
|
||
+ </arg>
|
||
|
||
</cmdsynopsis>
|
||
</refsynopsisdiv>
|
||
@@ -137,6 +140,19 @@
|
||
</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>
|
||
+
|
||
</variablelist>
|
||
</refsect1>
|
||
|
||
@@ -213,7 +229,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>
|
||
diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c
|
||
index ce2c21f5..9c1bdd87 100644
|
||
--- a/modules/pam_pwhistory/pam_pwhistory.c
|
||
+++ b/modules/pam_pwhistory/pam_pwhistory.c
|
||
@@ -69,6 +69,7 @@ struct options_t {
|
||
int enforce_for_root;
|
||
int remember;
|
||
int tries;
|
||
+ const char *filename;
|
||
};
|
||
typedef struct options_t options_t;
|
||
|
||
@@ -104,13 +105,23 @@ parse_option (pam_handle_t *pamh, const char *argv, options_t *options)
|
||
options->enforce_for_root = 1;
|
||
else if (pam_str_skip_icase_prefix(argv, "authtok_type=") != NULL)
|
||
{ /* ignore, for pam_get_authtok */; }
|
||
+ else if ((str = pam_str_skip_icase_prefix(argv, "file=")) != NULL)
|
||
+ {
|
||
+ if (*str != '/')
|
||
+ {
|
||
+ pam_syslog (pamh, LOG_ERR,
|
||
+ "pam_pwhistory: file path should be absolute: %s", argv);
|
||
+ }
|
||
+ else
|
||
+ options->filename = str;
|
||
+ }
|
||
else
|
||
pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv);
|
||
}
|
||
|
||
static int
|
||
run_save_helper(pam_handle_t *pamh, const char *user,
|
||
- int howmany, int debug)
|
||
+ int howmany, const char *filename, int debug)
|
||
{
|
||
int retval, child;
|
||
struct sigaction newsa, oldsa;
|
||
@@ -123,7 +134,7 @@ run_save_helper(pam_handle_t *pamh, const char *user,
|
||
if (child == 0)
|
||
{
|
||
static char *envp[] = { NULL };
|
||
- char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
|
||
+ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||
|
||
if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_PIPE_FD,
|
||
PAM_MODUTIL_PIPE_FD,
|
||
@@ -137,9 +148,10 @@ run_save_helper(pam_handle_t *pamh, const char *user,
|
||
args[0] = (char *)PWHISTORY_HELPER;
|
||
args[1] = (char *)"save";
|
||
args[2] = (char *)user;
|
||
+ args[3] = (char *)filename;
|
||
DIAG_POP_IGNORE_CAST_QUAL;
|
||
- if (asprintf(&args[3], "%d", howmany) < 0 ||
|
||
- asprintf(&args[4], "%d", debug) < 0)
|
||
+ if (asprintf(&args[4], "%d", howmany) < 0 ||
|
||
+ asprintf(&args[5], "%d", debug) < 0)
|
||
{
|
||
pam_syslog(pamh, LOG_ERR, "asprintf: %m");
|
||
_exit(PAM_SYSTEM_ERR);
|
||
@@ -185,7 +197,7 @@ run_save_helper(pam_handle_t *pamh, const char *user,
|
||
|
||
static int
|
||
run_check_helper(pam_handle_t *pamh, const char *user,
|
||
- const char *newpass, int debug)
|
||
+ const char *newpass, const char *filename, int debug)
|
||
{
|
||
int retval, child, fds[2];
|
||
struct sigaction newsa, oldsa;
|
||
@@ -202,7 +214,7 @@ run_check_helper(pam_handle_t *pamh, const char *user,
|
||
if (child == 0)
|
||
{
|
||
static char *envp[] = { NULL };
|
||
- char *args[] = { NULL, NULL, NULL, NULL, NULL };
|
||
+ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
|
||
|
||
/* reopen stdin as pipe */
|
||
if (dup2(fds[0], STDIN_FILENO) != STDIN_FILENO)
|
||
@@ -223,8 +235,9 @@ run_check_helper(pam_handle_t *pamh, const char *user,
|
||
args[0] = (char *)PWHISTORY_HELPER;
|
||
args[1] = (char *)"check";
|
||
args[2] = (char *)user;
|
||
+ args[3] = (char *)filename;
|
||
DIAG_POP_IGNORE_CAST_QUAL;
|
||
- if (asprintf(&args[3], "%d", debug) < 0)
|
||
+ if (asprintf(&args[4], "%d", debug) < 0)
|
||
{
|
||
pam_syslog(pamh, LOG_ERR, "asprintf: %m");
|
||
_exit(PAM_SYSTEM_ERR);
|
||
@@ -323,10 +336,10 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||
return PAM_SUCCESS;
|
||
}
|
||
|
||
- retval = save_old_pass (pamh, user, options.remember, options.debug);
|
||
+ retval = save_old_pass (pamh, user, options.remember, options.filename, options.debug);
|
||
|
||
if (retval == PAM_PWHISTORY_RUN_HELPER)
|
||
- retval = run_save_helper(pamh, user, options.remember, options.debug);
|
||
+ retval = run_save_helper(pamh, user, options.remember, options.filename, options.debug);
|
||
|
||
if (retval != PAM_SUCCESS)
|
||
return retval;
|
||
@@ -358,9 +371,9 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||
if (options.debug)
|
||
pam_syslog (pamh, LOG_DEBUG, "check against old password file");
|
||
|
||
- retval = check_old_pass (pamh, user, newpass, options.debug);
|
||
+ retval = check_old_pass (pamh, user, newpass, options.filename, options.debug);
|
||
if (retval == PAM_PWHISTORY_RUN_HELPER)
|
||
- retval = run_check_helper(pamh, user, newpass, options.debug);
|
||
+ retval = run_check_helper(pamh, user, newpass, options.filename, options.debug);
|
||
|
||
if (retval != PAM_SUCCESS)
|
||
{
|
||
diff --git a/modules/pam_pwhistory/pwhistory_helper.c b/modules/pam_pwhistory/pwhistory_helper.c
|
||
index b08a14a7..7a61ae53 100644
|
||
--- a/modules/pam_pwhistory/pwhistory_helper.c
|
||
+++ b/modules/pam_pwhistory/pwhistory_helper.c
|
||
@@ -51,7 +51,7 @@
|
||
|
||
|
||
static int
|
||
-check_history(const char *user, const char *debug)
|
||
+check_history(const char *user, const char *filename, const char *debug)
|
||
{
|
||
char pass[PAM_MAX_RESP_SIZE + 1];
|
||
char *passwords[] = { pass };
|
||
@@ -68,7 +68,7 @@ check_history(const char *user, const char *debug)
|
||
return PAM_AUTHTOK_ERR;
|
||
}
|
||
|
||
- retval = check_old_pass(user, pass, dbg);
|
||
+ retval = check_old_pass(user, pass, filename, dbg);
|
||
|
||
memset(pass, '\0', PAM_MAX_RESP_SIZE); /* clear memory of the password */
|
||
|
||
@@ -76,13 +76,13 @@ check_history(const char *user, const char *debug)
|
||
}
|
||
|
||
static int
|
||
-save_history(const char *user, const char *howmany, const char *debug)
|
||
+save_history(const char *user, const char *filename, const char *howmany, const char *debug)
|
||
{
|
||
int num = atoi(howmany);
|
||
int dbg = atoi(debug); /* no need to be too fancy here */
|
||
int retval;
|
||
|
||
- retval = save_old_pass(user, num, dbg);
|
||
+ retval = save_old_pass(user, num, filename, dbg);
|
||
|
||
return retval;
|
||
}
|
||
@@ -92,13 +92,14 @@ main(int argc, char *argv[])
|
||
{
|
||
const char *option;
|
||
const char *user;
|
||
+ const char *filename;
|
||
|
||
/*
|
||
* we establish that this program is running with non-tty stdin.
|
||
* this is to discourage casual use.
|
||
*/
|
||
|
||
- if (isatty(STDIN_FILENO) || argc < 4)
|
||
+ if (isatty(STDIN_FILENO) || argc < 5)
|
||
{
|
||
fprintf(stderr,
|
||
"This binary is not designed for running in this way.\n");
|
||
@@ -107,11 +108,12 @@ main(int argc, char *argv[])
|
||
|
||
option = argv[1];
|
||
user = argv[2];
|
||
+ filename = argv[3];
|
||
|
||
- if (strcmp(option, "check") == 0 && argc == 4)
|
||
- return check_history(user, argv[3]);
|
||
- else if (strcmp(option, "save") == 0 && argc == 5)
|
||
- return save_history(user, argv[3], argv[4]);
|
||
+ if (strcmp(option, "check") == 0 && argc == 5)
|
||
+ return check_history(user, filename, argv[4]);
|
||
+ else if (strcmp(option, "save") == 0 && argc == 6)
|
||
+ return save_history(user, filename, argv[4], argv[5]);
|
||
|
||
fprintf(stderr, "This binary is not designed for running in this way.\n");
|
||
|
||
diff --git a/modules/pam_rootok/pam_rootok.c b/modules/pam_rootok/pam_rootok.c
|
||
index dd374c53..9bc15abf 100644
|
||
--- a/modules/pam_rootok/pam_rootok.c
|
||
+++ b/modules/pam_rootok/pam_rootok.c
|
||
@@ -53,11 +53,10 @@ static int
|
||
PAM_FORMAT((printf, 2, 3))
|
||
log_callback (int type UNUSED, const char *fmt, ...)
|
||
{
|
||
- int audit_fd;
|
||
va_list ap;
|
||
|
||
#ifdef HAVE_LIBAUDIT
|
||
- audit_fd = audit_open();
|
||
+ int audit_fd = audit_open();
|
||
|
||
if (audit_fd >= 0) {
|
||
char *buf;
|
||
diff --git a/modules/pam_sepermit/Makefile.am b/modules/pam_sepermit/Makefile.am
|
||
index 18a89b60..bed3b149 100644
|
||
--- a/modules/pam_sepermit/Makefile.am
|
||
+++ b/modules/pam_sepermit/Makefile.am
|
||
@@ -13,7 +13,7 @@ dist_man_MANS = pam_sepermit.8 sepermit.conf.5
|
||
endif
|
||
XMLS = README.xml pam_sepermit.8.xml sepermit.conf.5.xml
|
||
dist_check_SCRIPTS = tst-pam_sepermit
|
||
-TESTS = $(dist_check_SCRIPTS)
|
||
+TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS)
|
||
|
||
securelibdir = $(SECUREDIR)
|
||
secureconfdir = $(SCONFIGDIR)
|
||
@@ -21,7 +21,6 @@ sepermitlockdir = ${localstatedir}/run/sepermit
|
||
|
||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||
-I$(top_srcdir)/libpam_misc/include \
|
||
- -D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\" \
|
||
-D SEPERMIT_LOCKDIR=\"$(sepermitlockdir)\" $(WARN_CFLAGS)
|
||
|
||
pam_sepermit_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBSELINUX@
|
||
@@ -33,6 +32,9 @@ endif
|
||
dist_secureconf_DATA = sepermit.conf
|
||
securelib_LTLIBRARIES = pam_sepermit.la
|
||
|
||
+check_PROGRAMS = tst-pam_sepermit-retval
|
||
+tst_pam_sepermit_retval_LDADD = $(top_builddir)/libpam/libpam.la
|
||
+
|
||
install-data-local:
|
||
mkdir -p $(DESTDIR)$(sepermitlockdir)
|
||
|
||
diff --git a/modules/pam_sepermit/pam_sepermit.8.xml b/modules/pam_sepermit/pam_sepermit.8.xml
|
||
index 30d9cc54..5763c346 100644
|
||
--- a/modules/pam_sepermit/pam_sepermit.8.xml
|
||
+++ b/modules/pam_sepermit/pam_sepermit.8.xml
|
||
@@ -54,7 +54,11 @@
|
||
<refentrytitle>sepermit.conf</refentrytitle><manvolnum>5</manvolnum>
|
||
</citerefentry> for details.
|
||
</para>
|
||
-
|
||
+ <para condition="with_vendordir">
|
||
+ If there is no explicitly specified configuration file and
|
||
+ <filename>/etc/security/sepermit.conf</filename> does not exist,
|
||
+ <filename>%vendordir%/security/sepermit.conf</filename> is used.
|
||
+ </para>
|
||
</refsect1>
|
||
|
||
<refsect1 id="pam_sepermit-options">
|
||
diff --git a/modules/pam_sepermit/pam_sepermit.c b/modules/pam_sepermit/pam_sepermit.c
|
||
index f7d98d5b..5fbc8fdd 100644
|
||
--- a/modules/pam_sepermit/pam_sepermit.c
|
||
+++ b/modules/pam_sepermit/pam_sepermit.c
|
||
@@ -61,6 +61,12 @@
|
||
|
||
#include <selinux/selinux.h>
|
||
|
||
+#include "pam_inline.h"
|
||
+
|
||
+#define SEPERMIT_CONF_FILE (SCONFIGDIR "/sepermit.conf")
|
||
+#ifdef VENDOR_SCONFIGDIR
|
||
+# define SEPERMIT_VENDOR_CONF_FILE (VENDOR_SCONFIGDIR "/sepermit.conf");
|
||
+#endif
|
||
#define MODULE "pam_sepermit"
|
||
#define OPT_DELIM ":"
|
||
|
||
@@ -370,16 +376,31 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
|
||
const char *user = NULL;
|
||
char *seuser = NULL;
|
||
char *level = NULL;
|
||
- const char *cfgfile = SEPERMIT_CONF_FILE;
|
||
+ const char *cfgfile = NULL;
|
||
|
||
/* Parse arguments. */
|
||
for (i = 0; i < argc; i++) {
|
||
+ const char *str;
|
||
+
|
||
if (strcmp(argv[i], "debug") == 0) {
|
||
debug = 1;
|
||
+ } else if ((str = pam_str_skip_prefix(argv[i], "conf=")) != NULL) {
|
||
+ cfgfile = str;
|
||
+ } else {
|
||
+ pam_syslog(pamh, LOG_ERR, "unknown option: %s", argv[i]);
|
||
}
|
||
- if (strcmp(argv[i], "conf=") == 0) {
|
||
- cfgfile = argv[i] + 5;
|
||
- }
|
||
+ }
|
||
+
|
||
+ if (cfgfile == NULL) {
|
||
+#ifdef SEPERMIT_VENDOR_CONF_FILE
|
||
+ struct stat buffer;
|
||
+
|
||
+ cfgfile = SEPERMIT_CONF_FILE;
|
||
+ if (stat(cfgfile, &buffer) != 0 && errno == ENOENT)
|
||
+ cfgfile = SEPERMIT_VENDOR_CONF_FILE;
|
||
+#else
|
||
+ cfgfile = SEPERMIT_CONF_FILE;
|
||
+#endif
|
||
}
|
||
|
||
if (debug)
|
||
diff --git a/modules/pam_sepermit/tst-pam_sepermit-retval.c b/modules/pam_sepermit/tst-pam_sepermit-retval.c
|
||
new file mode 100644
|
||
index 00000000..321bd6d1
|
||
--- /dev/null
|
||
+++ b/modules/pam_sepermit/tst-pam_sepermit-retval.c
|
||
@@ -0,0 +1,158 @@
|
||
+/*
|
||
+ * Check pam_sepermit return values and conf= option.
|
||
+ *
|
||
+ * Copyright (c) 2020-2022 Dmitry V. Levin <ldv@altlinux.org>
|
||
+ */
|
||
+
|
||
+#include "test_assert.h"
|
||
+
|
||
+#include <limits.h>
|
||
+#include <stdio.h>
|
||
+#include <string.h>
|
||
+#include <unistd.h>
|
||
+#include <security/pam_appl.h>
|
||
+
|
||
+#define MODULE_NAME "pam_sepermit"
|
||
+#define TEST_NAME "tst-" MODULE_NAME "-retval"
|
||
+
|
||
+static const char service_file[] = TEST_NAME ".service";
|
||
+static const char missing_file[] = TEST_NAME ".missing";
|
||
+static const char config_file[] = TEST_NAME ".conf";
|
||
+static struct pam_conv conv;
|
||
+
|
||
+int
|
||
+main(void)
|
||
+{
|
||
+ pam_handle_t *pamh = NULL;
|
||
+ FILE *fp;
|
||
+ char cwd[PATH_MAX];
|
||
+
|
||
+ ASSERT_NE(NULL, getcwd(cwd, sizeof(cwd)));
|
||
+
|
||
+ /* PAM_USER_UNKNOWN */
|
||
+ ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
||
+ ASSERT_LT(0,
|
||
+ fprintf(fp, "#%%PAM-1.0\n"
|
||
+ "auth required %s/.libs/%s.so\n"
|
||
+ "account required %s/.libs/%s.so\n"
|
||
+ "password required %s/.libs/%s.so\n"
|
||
+ "session required %s/.libs/%s.so\n",
|
||
+ cwd, MODULE_NAME,
|
||
+ cwd, MODULE_NAME,
|
||
+ cwd, MODULE_NAME,
|
||
+ cwd, MODULE_NAME));
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ ASSERT_EQ(PAM_SUCCESS,
|
||
+ pam_start_confdir(service_file, "", &conv, ".", &pamh));
|
||
+ ASSERT_NE(NULL, pamh);
|
||
+ ASSERT_EQ(PAM_USER_UNKNOWN, pam_authenticate(pamh, 0));
|
||
+ ASSERT_EQ(PAM_PERM_DENIED, pam_setcred(pamh, 0));
|
||
+ ASSERT_EQ(PAM_USER_UNKNOWN, pam_acct_mgmt(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_chauthtok(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_open_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_close_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||
+ pamh = NULL;
|
||
+
|
||
+ ASSERT_NE(NULL, fp = fopen(config_file, "w"));
|
||
+ ASSERT_LT(0, fprintf(fp, "nosuchuser:ignore\n"));
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ /*
|
||
+ * conf= specifies an existing file,
|
||
+ * PAM_IGNORE -> 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 conf=%s\n"
|
||
+ "account required %s/.libs/%s.so conf=%s\n"
|
||
+ "password required %s/.libs/%s.so conf=%s\n"
|
||
+ "session required %s/.libs/%s.so conf=%s\n",
|
||
+ cwd, MODULE_NAME, config_file,
|
||
+ cwd, MODULE_NAME, config_file,
|
||
+ cwd, MODULE_NAME, config_file,
|
||
+ cwd, MODULE_NAME, config_file));
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ ASSERT_EQ(PAM_SUCCESS,
|
||
+ pam_start_confdir(service_file, "root", &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_PERM_DENIED, pam_acct_mgmt(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_chauthtok(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_open_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_close_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||
+ pamh = NULL;
|
||
+
|
||
+ /*
|
||
+ * conf= specifies an existing file,
|
||
+ * PAM_IGNORE -> 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 conf=%s\n"
|
||
+ "auth required %s/../pam_permit/.libs/pam_permit.so\n"
|
||
+ "account required %s/.libs/%s.so conf=%s\n"
|
||
+ "account required %s/../pam_permit/.libs/pam_permit.so\n"
|
||
+ "password required %s/.libs/%s.so conf=%s\n"
|
||
+ "password required %s/../pam_permit/.libs/pam_permit.so\n"
|
||
+ "session required %s/.libs/%s.so conf=%s\n"
|
||
+ "session required %s/../pam_permit/.libs/pam_permit.so\n",
|
||
+ cwd, MODULE_NAME, config_file, cwd,
|
||
+ cwd, MODULE_NAME, config_file, cwd,
|
||
+ cwd, MODULE_NAME, config_file, cwd,
|
||
+ cwd, MODULE_NAME, config_file, cwd));
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ ASSERT_EQ(PAM_SUCCESS,
|
||
+ pam_start_confdir(service_file, "root", &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_SUCCESS, pam_acct_mgmt(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_chauthtok(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_open_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_close_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||
+ pamh = NULL;
|
||
+
|
||
+ /*
|
||
+ * conf= specifies a missing file,
|
||
+ * PAM_IGNORE -> 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 conf=%s\n"
|
||
+ "account required %s/.libs/%s.so conf=%s\n"
|
||
+ "password required %s/.libs/%s.so conf=%s\n"
|
||
+ "session required %s/.libs/%s.so conf=%s\n",
|
||
+ cwd, MODULE_NAME, missing_file,
|
||
+ cwd, MODULE_NAME, missing_file,
|
||
+ cwd, MODULE_NAME, missing_file,
|
||
+ cwd, MODULE_NAME, missing_file));
|
||
+ ASSERT_EQ(0, fclose(fp));
|
||
+
|
||
+ ASSERT_EQ(PAM_SUCCESS,
|
||
+ pam_start_confdir(service_file, "root", &conv, ".", &pamh));
|
||
+ ASSERT_NE(NULL, pamh);
|
||
+ ASSERT_EQ(PAM_SERVICE_ERR, 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_MODULE_UNKNOWN, pam_chauthtok(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_open_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_close_session(pamh, 0));
|
||
+ ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
||
+ pamh = NULL;
|
||
+
|
||
+ /* cleanup */
|
||
+ ASSERT_EQ(0, unlink(config_file));
|
||
+ ASSERT_EQ(0, unlink(service_file));
|
||
+
|
||
+ return 0;
|
||
+}
|
||
diff --git a/modules/pam_time/Makefile.am b/modules/pam_time/Makefile.am
|
||
index 833d51a6..f34f8dce 100644
|
||
--- a/modules/pam_time/Makefile.am
|
||
+++ b/modules/pam_time/Makefile.am
|
||
@@ -18,7 +18,7 @@ securelibdir = $(SECUREDIR)
|
||
secureconfdir = $(SCONFIGDIR)
|
||
|
||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||
- -DPAM_TIME_CONF=\"$(SCONFIGDIR)/time.conf\" $(WARN_CFLAGS)
|
||
+ $(WARN_CFLAGS)
|
||
AM_LDFLAGS = -no-undefined -avoid-version -module
|
||
if HAVE_VERSIONING
|
||
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||
diff --git a/modules/pam_time/pam_time.c b/modules/pam_time/pam_time.c
|
||
index 089ae22d..8eebc914 100644
|
||
--- a/modules/pam_time/pam_time.c
|
||
+++ b/modules/pam_time/pam_time.c
|
||
@@ -33,6 +33,8 @@
|
||
#include <libaudit.h>
|
||
#endif
|
||
|
||
+#define PAM_TIME_CONF (SCONFIGDIR "/time.conf")
|
||
+
|
||
#define PAM_TIME_BUFLEN 1000
|
||
#define FIELD_SEPARATOR ';' /* this is new as of .02 */
|
||
|
||
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
|
||
index f2474a5b..c8ab49f3 100644
|
||
--- a/modules/pam_unix/passverify.c
|
||
+++ b/modules/pam_unix/passverify.c
|
||
@@ -334,7 +334,7 @@ PAMH_ARG_DECL(int check_shadow_expiry,
|
||
|
||
#define PW_TMPFILE "/etc/npasswd"
|
||
#define SH_TMPFILE "/etc/nshadow"
|
||
-#define OPW_TMPFILE "/etc/security/nopasswd"
|
||
+#define OPW_TMPFILE SCONFIGDIR "/nopasswd"
|
||
|
||
/*
|
||
* i64c - convert an integer to a radix 64 character
|
||
diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h
|
||
index c07037d2..463ef185 100644
|
||
--- a/modules/pam_unix/passverify.h
|
||
+++ b/modules/pam_unix/passverify.h
|
||
@@ -8,7 +8,7 @@
|
||
|
||
#define PAM_UNIX_RUN_HELPER PAM_CRED_INSUFFICIENT
|
||
|
||
-#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
|
||
+#define OLD_PASSWORDS_FILE SCONFIGDIR "/opasswd"
|
||
|
||
int
|
||
is_pwd_shadowed(const struct passwd *pwd);
|
||
diff --git a/xtests/run-xtests.sh b/xtests/run-xtests.sh
|
||
index 14f585d9..ff9a4dc1 100755
|
||
--- a/xtests/run-xtests.sh
|
||
+++ b/xtests/run-xtests.sh
|
||
@@ -18,10 +18,12 @@ all=0
|
||
|
||
mkdir -p /etc/security
|
||
for config in access.conf group.conf time.conf limits.conf ; do
|
||
- cp /etc/security/$config /etc/security/$config-pam-xtests
|
||
+ [ -f "/etc/security/$config" ] &&
|
||
+ mv /etc/security/$config /etc/security/$config-pam-xtests
|
||
install -m 644 "${SRCDIR}"/$config /etc/security/$config
|
||
done
|
||
-mv /etc/security/opasswd /etc/security/opasswd-pam-xtests
|
||
+[ -f /etc/security/opasswd ] &&
|
||
+ mv /etc/security/opasswd /etc/security/opasswd-pam-xtests
|
||
|
||
for testname in $XTESTS ; do
|
||
for cfg in "${SRCDIR}"/$testname*.pamd ; do
|
||
@@ -47,11 +49,15 @@ for testname in $XTESTS ; do
|
||
all=`expr $all + 1`
|
||
rm -f /etc/pam.d/$testname*
|
||
done
|
||
-mv /etc/security/access.conf-pam-xtests /etc/security/access.conf
|
||
-mv /etc/security/group.conf-pam-xtests /etc/security/group.conf
|
||
-mv /etc/security/time.conf-pam-xtests /etc/security/time.conf
|
||
-mv /etc/security/limits.conf-pam-xtests /etc/security/limits.conf
|
||
-mv /etc/security/opasswd-pam-xtests /etc/security/opasswd
|
||
+
|
||
+for config in access.conf group.conf time.conf limits.conf opasswd ; do
|
||
+ if [ -f "/etc/security/$config-pam-xtests" ]; then
|
||
+ mv /etc/security/$config-pam-xtests /etc/security/$config
|
||
+ else
|
||
+ rm -f /etc/security/$config
|
||
+ fi
|
||
+done
|
||
+
|
||
if test "$failed" -ne 0; then
|
||
echo "==================="
|
||
echo "$failed of $all tests failed"
|