summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Schubert <schubi@suse.de>2021-12-03 14:33:20 +0100
committerThorsten Kukuk <5908016+thkukuk@users.noreply.github.com>2022-12-14 09:29:35 +0100
commit6135c45347b6173e305fda66eef138bde693b795 (patch)
treec67f2d947b9f9411268efb1f1ae1f611be0bb636
parentd71de05146d03c271bd5507724d24d1ad17c2be5 (diff)
downloadlinux-pam-git-6135c45347b6173e305fda66eef138bde693b795.tar.gz
pam_env: Use vendor specific pam_env.conf and environment as fallback
Use the vendor directory as fallback for a distribution provided default config if there is no one in /etc. * Makefile.am: Add libeconf setting. * pam_env.c: Take care about the fallback configuration in the vendor directory. * pam_env.8.xml: Add description for the vendor directory. * pam_env.conf.5.xml: Add description for the vendor directory. * tst-pam_env-retval.c: Add tests for libeconf. * configure.ac: Add ECONF settings for building man pages.
-rw-r--r--configure.ac12
-rw-r--r--modules/pam_env/.gitignore1
-rw-r--r--modules/pam_env/Makefile.am4
-rw-r--r--modules/pam_env/pam_env.8.xml48
-rw-r--r--modules/pam_env/pam_env.c298
-rw-r--r--modules/pam_env/pam_env.conf.5.xml20
-rw-r--r--modules/pam_env/tst-pam_env-retval.c60
7 files changed, 394 insertions, 49 deletions
diff --git a/configure.ac b/configure.ac
index 0892049e..538195e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -516,17 +516,17 @@ if test -n "$LIBSELINUX" ; then
LIBS=$BACKUP_LIBS
fi
+ECONF_CFLAGS=
+ECONF_LIBS=
AC_ARG_ENABLE([econf],
AS_HELP_STRING([--disable-econf], [do not use libeconf]),
- [WITH_ECONF=$enableval], WITH_ECONF=yes)
-if test "$WITH_ECONF" = "yes" ; then
- AC_CHECK_LIB([econf],[econf_readDirsWithCallback],[ECONF_LIBS="-leconf"],[ECONF_LIBS=""])
- if test -n "$ECONF_LIBS" ; then
- ECONF_CFLAGS="-DUSE_ECONF=1 $ECONF_CFLAGS"
- fi
+ [WITH_ECONF=$enableval], [WITH_ECONF=yes])
+if test "$WITH_ECONF" = "yes"; then
+ PKG_CHECK_MODULES([ECONF], [libeconf >= 0.5.0], [ECONF_CFLAGS="-DUSE_ECONF=1 $ECONF_CFLAGS"], [:])
fi
AC_SUBST([ECONF_CFLAGS])
AC_SUBST([ECONF_LIBS])
+
AC_ARG_ENABLE([vendordir],
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
if test -n "$enable_vendordir"; then
diff --git a/modules/pam_env/.gitignore b/modules/pam_env/.gitignore
new file mode 100644
index 00000000..4c5b234b
--- /dev/null
+++ b/modules/pam_env/.gitignore
@@ -0,0 +1 @@
+tst-pam_env-retval
diff --git a/modules/pam_env/Makefile.am b/modules/pam_env/Makefile.am
index 02cd9d37..b99a83ec 100644
--- a/modules/pam_env/Makefile.am
+++ b/modules/pam_env/Makefile.am
@@ -18,14 +18,14 @@ securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
- $(WARN_CFLAGS)
+ $(WARN_CFLAGS) -DSYSCONFDIR=\"$(sysconfdir)\" $(ECONF_CFLAGS)
AM_LDFLAGS = -no-undefined -avoid-version -module
if HAVE_VERSIONING
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
securelib_LTLIBRARIES = pam_env.la
-pam_env_la_LIBADD = $(top_builddir)/libpam/libpam.la
+pam_env_la_LIBADD = $(top_builddir)/libpam/libpam.la $(ECONF_LIBS)
check_PROGRAMS = tst-pam_env-retval
tst_pam_env_retval_LDADD = $(top_builddir)/libpam/libpam.la
diff --git a/modules/pam_env/pam_env.8.xml b/modules/pam_env/pam_env.8.xml
index 75ff862b..d7687d6c 100644
--- a/modules/pam_env/pam_env.8.xml
+++ b/modules/pam_env/pam_env.8.xml
@@ -52,13 +52,55 @@
variables as well as <emphasis>PAM_ITEM</emphasis>s such as
<emphasis>PAM_RHOST</emphasis>.
</para>
- <para>
+ <para condition="with_vendordir_and_with_econf">
+ Rules for (un)setting of variables can be defined in an own config
+ file. The path to this file can be specified with the
+ <emphasis>conffile</emphasis> option.
+ If this file does not exist, the default rules are taken from the
+ config files <filename>/etc/security/pam_env.conf</filename> and
+ <filename>/etc/security/pam_env.conf.d/*.conf</filename>.
+ If the file <filename>/etc/security/pam_env.conf</filename> does not
+ exist, the rules are taken from the files
+ <filename>%vendordir%/security/pam_env.conf</filename>,
+ <filename>%vendordir%/security/pam_env.conf.d/*.conf</filename> and
+ <filename>/etc/security/pam_env.conf.d/*.conf</filename> in that order.
+ </para>
+ <para condition="with_vendordir_and_without_econf">
+ By default rules for (un)setting of variables are taken from the
+ config file <filename>/etc/security/pam_env.conf</filename>.
+ If this file does not exist <filename>%vendordir%/security/pam_env.conf</filename> is used.
+ An alternate file can be specified with the <emphasis>conffile</emphasis>
+ option, which overrules all other files.
+ </para>
+ <para condition="without_vendordir">
By default rules for (un)setting of variables are taken from the
config file <filename>/etc/security/pam_env.conf</filename>. An
alternate file can be specified with the <emphasis>conffile</emphasis>
option.
</para>
- <para>
+ <para condition="with_vendordir_and_with_econf">
+ Environment variables can be defined in a file with simple <emphasis>KEY=VAL</emphasis>
+ pairs on separate lines. The path to this file can be specified with the
+ <emphasis>envfile</emphasis> option.
+ If this file has not been defined, the settings are read from the
+ files <filename>/etc/security/environment</filename> and
+ <filename>/etc/security/environment.d/*</filename>.
+ If the file <filename>/etc/environment</filename> does not exist, the
+ settings are read from the files <filename>%vendordir%/environment</filename>,
+ <filename>%vendordir%/environment.d/*</filename> and
+ <filename>/etc/environment.d/*</filename> in that order.
+ And last but not least, with the <emphasis>readenv</emphasis> option this mechanism can
+ be completely disabled.
+ </para>
+ <para condition="with_vendordir_and_without_econf">
+ Second a file (<filename>/etc/environment</filename> by default) with simple
+ <emphasis>KEY=VAL</emphasis> pairs on separate lines will be read.
+ If this file does not exist, <filename>%vendordir%/etc/environment</filename> is used.
+ With the <emphasis>envfile</emphasis> option an alternate file can be specified,
+ which overrules all other files.
+ And with the <emphasis>readenv</emphasis> option this can be completely disabled.
+ </para>
+ <para condition="without_vendordir">
Second a file (<filename>/etc/environment</filename> by default) with simple
<emphasis>KEY=VAL</emphasis> pairs on separate lines will be read.
With the <emphasis>envfile</emphasis> option an alternate file can be specified.
@@ -224,12 +266,14 @@
<title>FILES</title>
<variablelist>
<varlistentry>
+ <term condition="with_vendordir"><filename>/usr/etc/security/pam_env.conf</filename></term>
<term><filename>/etc/security/pam_env.conf</filename></term>
<listitem>
<para>Default configuration file</para>
</listitem>
</varlistentry>
<varlistentry>
+ <term condition="with_vendordir"><filename>/usr/etc/environment</filename></term>
<term><filename>/etc/environment</filename></term>
<listitem>
<para>Default environment file</para>
diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c
index 64a58645..aabab799 100644
--- a/modules/pam_env/pam_env.c
+++ b/modules/pam_env/pam_env.c
@@ -7,6 +7,9 @@
*/
#define DEFAULT_ETC_ENVFILE "/etc/environment"
+#ifdef VENDORDIR
+#define VENDOR_DEFAULT_ETC_ENVFILE (VENDORDIR "/etc/environment")
+#endif
#define DEFAULT_READ_ENVFILE 1
#define DEFAULT_USER_ENVFILE ".pam_environment"
@@ -25,6 +28,9 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#ifdef USE_ECONF
+#include <libeconf.h>
+#endif
#include <security/pam_modules.h>
#include <security/pam_modutil.h>
@@ -42,6 +48,9 @@ typedef struct var {
} VAR;
#define DEFAULT_CONF_FILE (SCONFIGDIR "/pam_env.conf")
+#ifdef VENDOR_SCONFIGDIR
+#define VENDOR_DEFAULT_CONF_FILE (VENDOR_SCONFIGDIR "/pam_env.conf")
+#endif
#define BUF_SIZE 8192
#define MAX_ENV 8192
@@ -56,6 +65,16 @@ typedef struct var {
/* This is a special value used to designate an empty string */
static char quote='\0';
+static void free_string_array(char **array)
+{
+ if (array == NULL)
+ return;
+ for (char **entry = array; *entry != NULL; ++entry) {
+ free(*entry);
+ }
+ free(array);
+}
+
/* argument parsing */
#define PAM_DEBUG_ARG 0x01
@@ -68,10 +87,10 @@ _pam_parse (const pam_handle_t *pamh, int argc, const char **argv,
int ctrl=0;
*user_envfile = DEFAULT_USER_ENVFILE;
- *envfile = DEFAULT_ETC_ENVFILE;
+ *envfile = NULL;
*readenv = DEFAULT_READ_ENVFILE;
*user_readenv = DEFAULT_USER_READ_ENVFILE;
- *conffile = DEFAULT_CONF_FILE;
+ *conffile = NULL;
/* step through arguments */
for (; argc-- > 0; ++argv) {
@@ -119,6 +138,148 @@ _pam_parse (const pam_handle_t *pamh, int argc, const char **argv,
return ctrl;
}
+#ifdef USE_ECONF
+
+#define ENVIRONMENT "environment"
+#define PAM_ENV "pam_env"
+
+static int
+isDirectory(const char *path) {
+ struct stat statbuf;
+ if (stat(path, &statbuf) != 0)
+ return 0;
+ return S_ISDIR(statbuf.st_mode);
+}
+
+static int
+econf_read_file(const pam_handle_t *pamh, const char *filename, const char *delim,
+ const char *name, const char *suffix, const char *subpath,
+ char ***lines)
+{
+ econf_file *key_file = NULL;
+ econf_err error;
+ size_t key_number = 0;
+ char **keys = NULL;
+ const char *base_dir = "";
+
+ if (filename != NULL) {
+ if (isDirectory(filename)) {
+ /* Set base directory which can be different from root */
+ D(("filename argument is a directory: %s", filename));
+ base_dir = filename;
+ } else {
+ /* Read only one file */
+ error = econf_readFile (&key_file, filename, delim, "#");
+ D(("File name is: %s", filename));
+ if (error != ECONF_SUCCESS) {
+ pam_syslog(pamh, LOG_ERR, "Unable to open env file: %s: %s", filename,
+ econf_errString(error));
+ if (error == ECONF_NOFILE)
+ return PAM_IGNORE;
+ else
+ return PAM_ABORT;
+ }
+ }
+ }
+ if (filename == NULL || base_dir[0] != '\0') {
+ /* Read and merge all setting in e.g. /usr/etc and /etc */
+ char *vendor_dir = NULL, *sysconf_dir;
+ if (subpath != NULL && subpath[0] != '\0') {
+#ifdef VENDORDIR
+ if (asprintf(&vendor_dir, "%s%s/%s/", base_dir, VENDORDIR, subpath) < 0) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ return PAM_BUF_ERR;
+ }
+#endif
+ if (asprintf(&sysconf_dir, "%s%s/%s/", base_dir, SYSCONFDIR, subpath) < 0) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ free(vendor_dir);
+ return PAM_BUF_ERR;
+ }
+ } else {
+#ifdef VENDORDIR
+ if (asprintf(&vendor_dir, "%s%s/", base_dir, VENDORDIR) < 0) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ return PAM_BUF_ERR;
+ }
+#endif
+ if (asprintf(&sysconf_dir, "%s%s/", base_dir, SYSCONFDIR) < 0) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ free(vendor_dir);
+ return PAM_BUF_ERR;
+ }
+ }
+
+ D(("Read configuration from directory %s and %s", vendor_dir, sysconf_dir));
+ error = econf_readDirs (&key_file, vendor_dir, sysconf_dir, name, suffix,
+ delim, "#");
+ free(vendor_dir);
+ free(sysconf_dir);
+ if (error != ECONF_SUCCESS) {
+ if (error == ECONF_NOFILE) {
+ pam_syslog(pamh, LOG_ERR, "Configuration file not found: %s%s", name, suffix);
+ return PAM_IGNORE;
+ } else {
+ char *error_filename = NULL;
+ uint64_t error_line = 0;
+
+ econf_errLocation(&error_filename, &error_line);
+ pam_syslog(pamh, LOG_ERR, "Unable to read configuration file %s line %ld: %s",
+ error_filename,
+ error_line,
+ econf_errString(error));
+ free(error_filename);
+ return PAM_ABORT;
+ }
+ }
+ }
+
+ error = econf_getKeys(key_file, NULL, &key_number, &keys);
+ if (error != ECONF_SUCCESS && error != ECONF_NOKEY) {
+ pam_syslog(pamh, LOG_ERR, "Unable to read keys: %s",
+ econf_errString(error));
+ econf_freeFile(key_file);
+ return PAM_ABORT;
+ }
+
+ *lines = malloc((key_number +1)* sizeof(char**));
+ if (*lines == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ econf_free(keys);
+ econf_freeFile(key_file);
+ return PAM_BUF_ERR;
+ }
+
+ (*lines)[key_number] = 0;
+
+ for (size_t i = 0; i < key_number; i++) {
+ char *val;
+
+ error = econf_getStringValue (key_file, NULL, keys[i], &val);
+ if (error != ECONF_SUCCESS) {
+ pam_syslog(pamh, LOG_ERR, "Unable to get string from key %s: %s",
+ keys[i],
+ econf_errString(error));
+ } else {
+ if (asprintf(&(*lines)[i],"%s%c%s", keys[i], delim[0], val) < 0) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ econf_free(keys);
+ econf_freeFile(key_file);
+ free_string_array(*lines);
+ free (val);
+ return PAM_BUF_ERR;
+ }
+ free (val);
+ }
+ }
+
+ econf_free(keys);
+ econf_free(key_file);
+ return PAM_SUCCESS;
+}
+
+#else
+
/*
* This is where we read a line of the PAM config file. The line may be
* preceded by lines of comments and also extended with "\\\n"
@@ -212,6 +373,52 @@ _assemble_line(FILE *f, char *buffer, int buf_len)
return used;
}
+static int read_file(const pam_handle_t *pamh, const char*filename, char ***lines)
+{
+ FILE *conf;
+ char buffer[BUF_SIZE];
+
+ D(("Parsed file name is: %s", filename));
+
+ if ((conf = fopen(filename,"r")) == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Unable to open env file: %s", filename);
+ return PAM_IGNORE;
+ }
+
+ size_t i = 0;
+ *lines = malloc((i + 1)* sizeof(char**));
+ if (*lines == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ (void) fclose(conf);
+ return PAM_BUF_ERR;
+ }
+ (*lines)[i] = 0;
+ while (_assemble_line(conf, buffer, BUF_SIZE) > 0) {
+ char **tmp = NULL;
+ D(("Read line: %s", buffer));
+ tmp = realloc(*lines, (++i + 1) * sizeof(char**));
+ if (tmp == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ (void) fclose(conf);
+ free_string_array(*lines);
+ return PAM_BUF_ERR;
+ }
+ *lines = tmp;
+ (*lines)[i-1] = strdup(buffer);
+ if ((*lines)[i-1] == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
+ (void) fclose(conf);
+ free_string_array(*lines);
+ return PAM_BUF_ERR;
+ }
+ (*lines)[i] = 0;
+ }
+
+ (void) fclose(conf);
+ return PAM_SUCCESS;
+}
+#endif
+
static int
_parse_line(const pam_handle_t *pamh, const char *buffer, VAR *var)
{
@@ -626,34 +833,38 @@ static int
_parse_config_file(pam_handle_t *pamh, int ctrl, const char *file)
{
int retval;
- char buffer[BUF_SIZE];
- FILE *conf;
VAR Var, *var=&Var;
-
- D(("Called."));
+ char **conf_list = NULL;
var->name=NULL; var->defval=NULL; var->override=NULL;
- D(("Config file name is: %s", file));
+ D(("Called."));
+#ifdef USE_ECONF
+ /* If "file" is not NULL, only this file will be parsed. */
+ retval = econf_read_file(pamh, file, " \t", PAM_ENV, ".conf", "security", &conf_list);
+#else
+ /* Only one file will be parsed. So, file has to be set. */
+ if (file == NULL) /* No filename has been set via argv. */
+ file = DEFAULT_CONF_FILE;
+#ifdef VENDOR_DEFAULT_CONF_FILE
/*
- * Lets try to open the config file, parse it and process
- * any variables found.
- */
-
- if ((conf = fopen(file,"r")) == NULL) {
- pam_syslog(pamh, LOG_ERR, "Unable to open config file: %s: %m", file);
- return PAM_IGNORE;
+ * Check whether file is available.
+ * If it does not exist, fall back to VENDOR_DEFAULT_CONF_FILE file.
+ */
+ struct stat stat_buffer;
+ if (stat(file, &stat_buffer) != 0 && errno == ENOENT) {
+ file = VENDOR_DEFAULT_CONF_FILE;
}
+#endif
+ retval = read_file(pamh, file, &conf_list);
+#endif
- /* _pam_assemble_line will provide a complete line from the config file,
- * with all comments removed and any escaped newlines fixed up
- */
-
- while (( retval = _assemble_line(conf, buffer, BUF_SIZE)) > 0) {
- D(("Read line: %s", buffer));
+ if (retval != PAM_SUCCESS)
+ return retval;
- if ((retval = _parse_line(pamh, buffer, var)) == GOOD_LINE) {
+ for (char **conf = conf_list; *conf != NULL; ++conf) {
+ if ((retval = _parse_line(pamh, *conf, var)) == GOOD_LINE) {
retval = _check_var(pamh, var);
if (DEFINE_VAR == retval) {
@@ -668,11 +879,10 @@ _parse_config_file(pam_handle_t *pamh, int ctrl, const char *file)
_clean_var(var);
- } /* while */
-
- (void) fclose(conf);
+ } /* for */
/* tidy up */
+ free_string_array(conf_list);
_clean_var(var); /* We could have got here prematurely,
* this is safe though */
D(("Exit."));
@@ -683,19 +893,33 @@ static int
_parse_env_file(pam_handle_t *pamh, int ctrl, const char *file)
{
int retval=PAM_SUCCESS, i, t;
- char buffer[BUF_SIZE], *key, *mark;
- FILE *conf;
-
- D(("Env file name is: %s", file));
-
- if ((conf = fopen(file,"r")) == NULL) {
- pam_syslog(pamh, LOG_ERR, "Unable to open env file: %s: %m", file);
- return PAM_IGNORE;
+ char *key, *mark;
+ char **env_list = NULL;
+
+#ifdef USE_ECONF
+ retval = econf_read_file(pamh, file, "=", ENVIRONMENT, "", "", &env_list);
+#else
+ /* Only one file will be parsed. So, file has to be set. */
+ if (file == NULL) /* No filename has been set via argv. */
+ file = DEFAULT_ETC_ENVFILE;
+#ifdef VENDOR_DEFAULT_ETC_ENVFILE
+ /*
+ * Check whether file is available.
+ * If it does not exist, fall back to VENDOR_DEFAULT_ETC_ENVFILE; file.
+ */
+ struct stat stat_buffer;
+ if (stat(file, &stat_buffer) != 0 && errno == ENOENT) {
+ file = VENDOR_DEFAULT_ETC_ENVFILE;
}
+#endif
+ retval = read_file(pamh, file, &env_list);
+#endif
- while (_assemble_line(conf, buffer, BUF_SIZE) > 0) {
- D(("Read line: %s", buffer));
- key = buffer;
+ if (retval != PAM_SUCCESS)
+ return retval == PAM_IGNORE ? PAM_SUCCESS : retval;
+
+ for (char **env = env_list; *env != NULL; ++env) {
+ key = *env;
/* skip leading white space */
key += strspn(key, " \n\t");
@@ -767,11 +991,11 @@ _parse_env_file(pam_handle_t *pamh, int ctrl, const char *file)
pam_syslog(pamh, LOG_DEBUG,
"pam_putenv(\"%s\")", key);
}
+ free(*env);
}
- (void) fclose(conf);
-
/* tidy up */
+ free(env_list);
D(("Exit."));
return retval;
}
diff --git a/modules/pam_env/pam_env.conf.5.xml b/modules/pam_env/pam_env.conf.5.xml
index fca046fe..5c0dbcb8 100644
--- a/modules/pam_env/pam_env.conf.5.xml
+++ b/modules/pam_env/pam_env.conf.5.xml
@@ -20,7 +20,15 @@
<refsect1 id='pam_env.conf-description'>
<title>DESCRIPTION</title>
- <para>
+ <para condition="with_vendordir">
+ The <filename>/usr/etc/security/pam_env.conf</filename> and
+ <filename>/etc/security/pam_env.conf</filename> files specify
+ the environment variables to be set, unset or modified by
+ <citerefentry><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ When someone logs in, these files are read and the environment
+ variables are set according.
+ </para>
+ <para condition="without_vendordir">
The <filename>/etc/security/pam_env.conf</filename> file specifies
the environment variables to be set, unset or modified by
<citerefentry><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
@@ -61,7 +69,15 @@
at front) can be used to mark this line as a comment line.
</para>
- <para>
+ <para condition="with_vendordir">
+ The <filename>/usr/etc/environment</filename> and <filename>/etc/environment</filename> files specify
+ the environment variables to be set. These files must consist of simple
+ <emphasis>NAME=VALUE</emphasis> pairs on separate lines.
+ The <citerefentry><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ module will read these files after the <filename>pam_env.conf</filename>
+ file.
+ </para>
+ <para condition="without_vendordir">
The <filename>/etc/environment</filename> file specifies
the environment variables to be set. The file must consist of simple
<emphasis>NAME=VALUE</emphasis> pairs on separate lines.
diff --git a/modules/pam_env/tst-pam_env-retval.c b/modules/pam_env/tst-pam_env-retval.c
index 6b9b3065..99e2e2a5 100644
--- a/modules/pam_env/tst-pam_env-retval.c
+++ b/modules/pam_env/tst-pam_env-retval.c
@@ -17,11 +17,18 @@
#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;
@@ -30,6 +37,11 @@ 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"
@@ -41,6 +53,18 @@ setup(void)
"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
@@ -48,6 +72,12 @@ 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
@@ -191,6 +221,36 @@ main(void)
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));