diff options
author | Stefan Schubert <schubi@suse.de> | 2022-02-16 11:51:35 +0100 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2022-06-30 09:48:52 +0000 |
commit | 543e122a80e25e9597cff418b837e214114bad1f (patch) | |
tree | 62c826f7198a6b5533144a690c0ad35c9141ea7b /modules | |
parent | 21affb5b1b90e3d0ac36556c5536ee81ef08aca4 (diff) | |
download | pam-543e122a80e25e9597cff418b837e214114bad1f.tar.gz pam-543e122a80e25e9597cff418b837e214114bad1f.tar.bz2 pam-543e122a80e25e9597cff418b837e214114bad1f.zip |
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.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/pam_namespace/namespace.conf.5.xml | 18 | ||||
-rw-r--r-- | modules/pam_namespace/pam_namespace.8.xml | 30 | ||||
-rw-r--r-- | modules/pam_namespace/pam_namespace.c | 128 | ||||
-rw-r--r-- | modules/pam_namespace/pam_namespace.h | 6 |
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 */ |