summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Schubert <schubi@suse.de>2022-02-16 11:51:35 +0100
committerDmitry V. Levin <ldv@altlinux.org>2022-06-30 09:48:52 +0000
commit543e122a80e25e9597cff418b837e214114bad1f (patch)
tree62c826f7198a6b5533144a690c0ad35c9141ea7b
parent21affb5b1b90e3d0ac36556c5536ee81ef08aca4 (diff)
downloadlinux-pam-git-543e122a80e25e9597cff418b837e214114bad1f.tar.gz
pam_namespace: use vendor specific namespace.conf and namespace.init as fallback
Use the vendor directory as fallback for a distribution provided default config and scripts if there is no configuration in /etc. pam_namespace.c: Take care about the fallback configuration in vendor directory. pam_namespace.h: Define vendor specific files and directories. pam_namespace.8.xml: Add description for vendor directories and files. namespace.conf.5.xml: Add description for vendor directories and files.
-rw-r--r--modules/pam_namespace/namespace.conf.5.xml18
-rw-r--r--modules/pam_namespace/pam_namespace.8.xml30
-rw-r--r--modules/pam_namespace/pam_namespace.c128
-rw-r--r--modules/pam_namespace/pam_namespace.h6
4 files changed, 167 insertions, 15 deletions
diff --git a/modules/pam_namespace/namespace.conf.5.xml b/modules/pam_namespace/namespace.conf.5.xml
index a94b49e2..67f8c043 100644
--- a/modules/pam_namespace/namespace.conf.5.xml
+++ b/modules/pam_namespace/namespace.conf.5.xml
@@ -30,13 +30,29 @@
directory path and the instance directory path as its arguments.
</para>
- <para>
+ <para condition="without_vendordir">
The <filename>/etc/security/namespace.conf</filename> file specifies
which directories are polyinstantiated, how they are polyinstantiated,
how instance directories would be named, and any users for whom
polyinstantiation would not be performed.
</para>
+ <para condition="with_vendordir">
+ The <filename>/etc/security/namespace.conf</filename> file
+ ( or <filename>%vendordir%/security/namespace.conf</filename> if it does
+ not exist) specifies which directories are polyinstantiated, how they are
+ polyinstantiated, how instance directories would be named, and any users
+ for whom polyinstantiation would not be performed.
+ Then individual <filename>*.conf</filename> files from the
+ <filename>/etc/security/namespace.d/</filename> and
+ <filename>%vendordir%/security/namespace.d</filename> directories are taken too.
+ If <filename>/etc/security/namespace.d/@filename@.conf</filename> exists, then
+ <filename>%vendordir%/security/namespace.d/@filename@.conf</filename> will not be used.
+ All <filename>namespace.d/*.conf</filename> files are sorted by their
+ <filename>@filename@.conf</filename> in lexicographic order regardless of which
+ of the directories they reside in.
+ </para>
+
<para>
When someone logs in, the file <filename>namespace.conf</filename> is
scanned. Comments are marked by <emphasis>#</emphasis> characters.
diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml
index 57c44c4b..ddaa00b4 100644
--- a/modules/pam_namespace/pam_namespace.8.xml
+++ b/modules/pam_namespace/pam_namespace.8.xml
@@ -74,6 +74,12 @@
and the user name as its arguments.
</para>
+ <para condition="with_vendordir">
+ If <filename>/etc/security/namespace.init</filename> does not exist,
+ <filename>%vendordir%/security/namespace.init</filename> is the
+ alternative to be used for it.
+ </para>
+
<para>
The pam_namespace module disassociates the session namespace from
the parent namespace. Any mounts/unmounts performed in the parent
@@ -313,6 +319,14 @@
</listitem>
</varlistentry>
+ <varlistentry condition="with_vendordir">
+ <term><filename>%vendordir%/security/namespace.conf</filename></term>
+ <listitem>
+ <para>Default configuration file if
+ <filename>/etc/security/namespace.conf</filename> does not exist.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><filename>/etc/security/namespace.d</filename></term>
<listitem>
@@ -320,12 +334,28 @@
</listitem>
</varlistentry>
+ <varlistentry condition="with_vendordir">
+ <term><filename>%vendordir%/security/namespace.d</filename></term>
+ <listitem>
+ <para>Directory for additional vendor specific configuration files.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><filename>/etc/security/namespace.init</filename></term>
<listitem>
<para>Init script for instance directories</para>
</listitem>
</varlistentry>
+
+ <varlistentry condition="with_vendordir">
+ <term><filename>%vendordir%/security/namespace.init</filename></term>
+ <listitem>
+ <para>Vendor init script for instance directories if
+ /etc/security/namespace.init does not exist.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
index 4d4188d0..017d5019 100644
--- a/modules/pam_namespace/pam_namespace.c
+++ b/modules/pam_namespace/pam_namespace.c
@@ -39,6 +39,94 @@
#include "pam_namespace.h"
#include "argv_parse.h"
+/* --- evaluting all files in VENDORDIR/security/namespace.d and /etc/security/namespace.d --- */
+static const char *base_name(const char *path)
+{
+ const char *base = strrchr(path, '/');
+ return base ? base+1 : path;
+}
+
+static int
+compare_filename(const void *a, const void *b)
+{
+ return strcmp(base_name(* (char * const *) a),
+ base_name(* (char * const *) b));
+}
+
+/* Evaluating a list of files which have to be parsed in the right order:
+ *
+ * - If etc/security/namespace.d/@filename@.conf exists, then
+ * %vendordir%/security/namespace.d/@filename@.conf should not be used.
+ * - All files in both namespace.d directories are sorted by their @filename@.conf in
+ * lexicographic order regardless of which of the directories they reside in. */
+static char **read_namespace_dir(struct instance_data *idata)
+{
+ glob_t globbuf;
+ size_t i=0;
+ int glob_rv = glob(NAMESPACE_D_GLOB, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
+ char **file_list;
+ size_t file_list_size = glob_rv == 0 ? globbuf.gl_pathc : 0;
+
+#ifdef VENDOR_NAMESPACE_D_GLOB
+ glob_t globbuf_vendor;
+ int glob_rv_vendor = glob(VENDOR_NAMESPACE_D_GLOB, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf_vendor);
+ if (glob_rv_vendor == 0)
+ file_list_size += globbuf_vendor.gl_pathc;
+#endif
+ file_list = malloc((file_list_size + 1) * sizeof(char*));
+ if (file_list == NULL) {
+ pam_syslog(idata->pamh, LOG_ERR, "Cannot allocate memory for file list: %m");
+#ifdef VENDOR_NAMESPACE_D_GLOB
+ if (glob_rv_vendor == 0)
+ globfree(&globbuf_vendor);
+#endif
+ if (glob_rv == 0)
+ globfree(&globbuf);
+ return NULL;
+ }
+
+ if (glob_rv == 0) {
+ for (i = 0; i < globbuf.gl_pathc; i++) {
+ file_list[i] = strdup(globbuf.gl_pathv[i]);
+ if (file_list[i] == NULL) {
+ pam_syslog(idata->pamh, LOG_ERR, "strdup failed: %m");
+ break;
+ }
+ }
+ }
+#ifdef VENDOR_NAMESPACE_D_GLOB
+ if (glob_rv_vendor == 0) {
+ for (size_t j = 0; j < globbuf_vendor.gl_pathc; j++) {
+ if (glob_rv == 0 && globbuf.gl_pathc > 0) {
+ int double_found = 0;
+ for (size_t k = 0; k < globbuf.gl_pathc; k++) {
+ if (strcmp(base_name(globbuf.gl_pathv[k]),
+ base_name(globbuf_vendor.gl_pathv[j])) == 0) {
+ double_found = 1;
+ break;
+ }
+ }
+ if (double_found)
+ continue;
+ }
+ file_list[i] = strdup(globbuf_vendor.gl_pathv[j]);
+ if (file_list[i] == NULL) {
+ pam_syslog(idata->pamh, LOG_ERR, "strdup failed: %m");
+ break;
+ }
+ i++;
+ }
+ globfree(&globbuf_vendor);
+ }
+#endif
+ file_list[i] = NULL;
+ qsort(file_list, i, sizeof(char *), compare_filename);
+ if (glob_rv == 0)
+ globfree(&globbuf);
+
+ return file_list;
+}
+
/*
* Adds an entry for a polyinstantiated directory to the linked list of
* polyinstantiated directories. It is called from process_line() while
@@ -624,8 +712,6 @@ static int parse_config_file(struct instance_data *idata)
char *line;
int retval;
size_t len = 0;
- glob_t globbuf;
- const char *oldlocale;
size_t n;
/*
@@ -664,13 +750,16 @@ static int parse_config_file(struct instance_data *idata)
* process_line to process each line.
*/
- memset(&globbuf, '\0', sizeof(globbuf));
- oldlocale = setlocale(LC_COLLATE, "C");
- glob(NAMESPACE_D_GLOB, 0, NULL, &globbuf);
- if (oldlocale != NULL)
- setlocale(LC_COLLATE, oldlocale);
-
confname = PAM_NAMESPACE_CONFIG;
+#ifdef VENDOR_PAM_NAMESPACE_CONFIG
+ /* Check whether PAM_NAMESPACE_CONFIG file is available.
+ * If it does not exist, fall back to VENDOR_PAM_NAMESPACE_CONFIG file. */
+ struct stat buffer;
+ if (stat(confname, &buffer) != 0 && errno == ENOENT) {
+ confname = VENDOR_PAM_NAMESPACE_CONFIG;
+ }
+#endif
+ char **filename_list = read_namespace_dir(idata);
n = 0;
for (;;) {
if (idata->flags & PAMNS_DEBUG)
@@ -680,7 +769,6 @@ static int parse_config_file(struct instance_data *idata)
if (fil == NULL) {
pam_syslog(idata->pamh, LOG_ERR, "Error opening config file %s",
confname);
- globfree(&globbuf);
free(rhome);
free(home);
return PAM_SERVICE_ERR;
@@ -698,7 +786,6 @@ static int parse_config_file(struct instance_data *idata)
"Error processing conf file %s line %s", confname, line);
fclose(fil);
free(line);
- globfree(&globbuf);
free(rhome);
free(home);
return PAM_SERVICE_ERR;
@@ -707,14 +794,18 @@ static int parse_config_file(struct instance_data *idata)
fclose(fil);
free(line);
- if (n >= globbuf.gl_pathc)
+ if (filename_list == NULL || filename_list[n] == NULL)
break;
- confname = globbuf.gl_pathv[n];
- n++;
+ confname = filename_list[n++];
+ }
+
+ if (filename_list != NULL) {
+ for (size_t i = 0; filename_list[i] != NULL; i++)
+ free(filename_list[i]);
+ free(filename_list);
}
- globfree(&globbuf);
free(rhome);
free(home);
@@ -1254,6 +1345,15 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath,
int status;
const char *init_script = NAMESPACE_INIT_SCRIPT;
+#ifdef VENDOR_NAMESPACE_INIT_SCRIPT
+ /* Check whether NAMESPACE_INIT_SCRIPT file is available.
+ * If it does not exist, fall back to VENDOR_NAMESPACE_INIT_SCRIPT file. */
+ struct stat buffer;
+ if (stat(init_script, &buffer) != 0 && errno == ENOENT) {
+ init_script = VENDOR_NAMESPACE_INIT_SCRIPT;
+ }
+#endif
+
memset(&newsa, '\0', sizeof(newsa));
newsa.sa_handler = SIG_DFL;
if (sigaction(SIGCHLD, &newsa, &oldsa) == -1) {
diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h
index 169bd59f..0b974ea7 100644
--- a/modules/pam_namespace/pam_namespace.h
+++ b/modules/pam_namespace/pam_namespace.h
@@ -94,6 +94,12 @@
#define NAMESPACE_INIT_SCRIPT (SCONFIGDIR "/namespace.init")
#define NAMESPACE_D_DIR (SCONFIGDIR "/namespace.d/")
#define NAMESPACE_D_GLOB (SCONFIGDIR "/namespace.d/*.conf")
+#ifdef VENDOR_SCONFIGDIR
+#define VENDOR_NAMESPACE_INIT_SCRIPT (VENDOR_SCONFIGDIR "/namespace.init")
+#define VENDOR_PAM_NAMESPACE_CONFIG (VENDOR_SCONFIGDIR "/namespace.conf")
+#define VENDOR_NAMESPACE_D_DIR (VENDOR_SCONFIGDIR "/namespace.d/")
+#define VENDOR_NAMESPACE_D_GLOB (VENDOR_SCONFIGDIR "/namespace.d/*.conf")
+#endif
/* module flags */
#define PAMNS_DEBUG 0x00000100 /* Running in debug mode */