[redhat-lspp] Re: [PATCH] pam_namespace module patch
Janak Desai
janak at us.ibm.com
Mon Feb 20 15:34:16 UTC 2006
Klaus Weidner wrote:
>On Fri, Feb 17, 2006 at 06:17:32PM -0500, JANAK DESAI wrote:
>
>
>>Changes since the -v1 of the patch available at the above location:
>> - Added user name in the instance directory name if polyinstantiation
>> is being done with USER or BOTH (both user and security context)
>>
>>
>
>This should be local policy and not hardcoded... I personally definitely
>want the username in the home directory names as well (even though those
>are not user instantiated), and don't want the directories hidden.
>
>This patch (on top of Janak's new patch) adds rudimentary variable
>expansion, and puts the filename patterns in the config file:
>
> /tmp /tmp.inst-$USER- both root,adm
> $HOME $HOME.inst- context
>
>This results in the following filenames:
>
> /tmp.inst-kw-9d3cb6031d5ea2d160a2bf80a123fbab
> /home/kw.inst-b3aabde70434ffd30d62c76cba31d321
>
>Using the following config gets the original behavior back (I've removed
>support for $HOME_PARENT, this could be added back if people really want
>it):
>
>
$HOME_PARENT may be useful when home directories /home1, /home2 etc.
Also, if by default polyinstantiation is needed for home directories,
then the admin
doesn't have to remember to add any non-standard (anything other than
/home/user)
home directory to the /etc/security/namespace.conf file.
This also exposed a current problem with the namespace module, which
will deny
login if the directory to polyinstantiate doesn't exist. I think that's
too severe.
If the directory to polinstantiate doesn't exist, the module should skip
that line.
I will add an access(dir, F_OK) call to the parsing routine to skip
namespace.conf
lines that are trying to polyinstantiate non-existent directories.
> /tmp /.inst- both root,adm
> $HOME /home/.inst- context
>
>Warning: I've modified the hash calculation slightly to avoid
>invalidating the hash if the prefix changes - if you depend on the old
>names this part should be reverted. I hope nobody is using this on a
>production system yet...
>
>Also, I've removed duplication between the README and the sample config
>to simplify editing while this is still in flux, we can re-expand that
>later.
>
>Signed-off-by: Klaus Weidner <klaus at atsec.com>
>
> README | 36 +++++++-------
> namespace.conf | 38 +--------------
> pam_namespace.c | 138 +++++++++++++++++++-------------------------------------
> 3 files changed, 71 insertions(+), 141 deletions(-)
>
>diff -ur Janak/namespace.conf ./namespace.conf
>--- Janak/namespace.conf 2006-02-17 02:34:28.000000000 -0600
>+++ ./namespace.conf 2006-02-17 03:14:36.000000000 -0600
>@@ -1,35 +1,6 @@
> # /etc/security/namespace.conf
> #
>-# Each line describes a limit for a user in the form:
>-#
>-# <polydir> <instance_parent_dir> <method> <list_of_uids>
>-#
>-# Where:
>-# <polydir> - is the absolute pathname of the directory to polyinstantiate
>-# Special entry $HOME is supported to designate user's home directory.
>-# This field cannot be blank.
>-#
>-# <instance_parent_dir> - is the absolute pathname of the parent directory
>-# where an instantiation of <polydir> is to be created. This instance
>-# is bind mounted on the <polydir> to provide an instance of <polydir>
>-# based on the <method> column. Two special entries $HOME and
>-# $HOME_PARENT are supported to designate user's home directory and
>-# parent of user's home directory. This field cannot be blank.
>-#
>-# <method> - is the method used for polyinstantiation. It can take 3 different
>-# values; "user" for polyinstantiation based on user name, "context"
>-# for polyinstantiation based on process security context, and "both"
>-# for polyinstantiation based on both user name and security context.
>-# Methods "context" and "both" are only available with SELinux. This
>-# field cannot be blank.
>-#
>-# <list_of_uids> - is a comma separated list of user names for whom the
>-# poyinstantiation is not performed. If left blank, polyinstantiation
>-# will be performed for all users.
>-#
>-# EXAMPLE /etc/security/namespace.conf configuration file:
>-# =======================================================
>-# comments
>+# See /usr/share/doc/pam-*/txts/README.pam_namespace for more information.
> #
> # Following two lines will polyinstantiate /tmp directory and user's home
> # directory. /tmp will be polyinstantiated based on both security context
>@@ -38,7 +9,6 @@
> # for user root and adm for directory /tmp, where as home directories
> # are polyinstantiated for all users.
> #
>-# /tmp / both root,adm
>-#
>-# $HOME $HOME_PARENT context
>-#
>+# /tmp /tmp.inst-$USER- both root,adm
>+# /var/tmp /var/tmp.inst-$USER- both root,adm
>+# $HOME $HOME.inst- context
>diff -ur Janak/pam_namespace.c ./pam_namespace.c
>--- Janak/pam_namespace.c 2006-02-17 02:34:28.000000000 -0600
>+++ ./pam_namespace.c 2006-02-17 03:29:12.000000000 -0600
>@@ -71,7 +71,6 @@
> /*
> * Module defines
> */
>-#define PROC_MNTS "/proc/mounts"
> #define MD5_DIGEST_LENGTH 16
> #ifndef PAM_NAMESPACE_CONFIG
> #define PAM_NAMESPACE_CONFIG "/etc/security/namespace.conf"
>@@ -109,7 +108,7 @@
> */
> struct polydir_s {
> char dir[PATH_MAX]; /* directory to polyinstantiate */
>- char instance_parent_dir[PATH_MAX]; /* parent dir of instance */
>+ char instance_prefix[PATH_MAX]; /* prefix for instance dir path name */
> enum polymethod method; /* method used to polyinstantiate */
> unsigned int num_uids; /* number of override uids */
> uid_t *uid; /* list of override uids */
>@@ -149,7 +148,7 @@
>
> /* Make copy */
> strcpy(pent->dir, ent->dir);
>- strcpy(pent->instance_parent_dir, ent->instance_parent_dir);
>+ strcpy(pent->instance_prefix, ent->instance_prefix);
> pent->method = ent->method;
> pent->num_uids = ent->num_uids;
> if (ent->num_uids) {
>@@ -186,8 +185,8 @@
>
> pam_syslog(idata->pamh, LOG_NOTICE, "Poly dirs so far");
> while (dptr) {
>- pam_syslog(idata->pamh, LOG_NOTICE, "%s %s %d", dptr->dir,
>- dptr->instance_parent_dir, dptr->method);
>+ pam_syslog(idata->pamh, LOG_NOTICE, "dir='%s' iprefix='%s' meth=%d",
>+ dptr->dir, dptr->instance_prefix, dptr->method);
> for (i = 0, iptr = dptr->uid; i < dptr->num_uids; i++, iptr++)
> pam_syslog(idata->pamh, LOG_NOTICE, "override user %d ", *iptr);
> dptr = dptr->next;
>@@ -224,10 +223,9 @@
> static int process_line(char *line, const char *home,
> struct instance_data *idata)
> {
>- const char *dir, *instance_parent_dir;
>+ const char *dir, *instance_prefix;
> const char *method, *uids;
> char *tmp = strdupa(home);
>- const char *parent_home_dir = dirname(tmp); /* parent of homedir */
> char *tptr;
> struct polydir_s poly;
> int retval = 0;
>@@ -270,8 +268,8 @@
> pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line -- skipping");
> return 0;
> }
>- instance_parent_dir = strtok_r(NULL, " \t", &tptr);
>- if (instance_parent_dir == NULL) {
>+ instance_prefix = strtok_r(NULL, " \t", &tptr);
>+ if (instance_prefix == NULL) {
> pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line -- skipping");
> return 0;
> }
>@@ -297,24 +295,33 @@
> */
> if (strcmp(dir, "$HOME") == 0) {
> dir = home;
>- /*
>- * For $HOME_PARENT, use the passed in home directory
>- * to obtain the parent of home directory.
>- */
>- if (strcmp(instance_parent_dir, "$HOME_PARENT") == 0)
>- instance_parent_dir = parent_home_dir;
>- else if (strcmp(instance_parent_dir, "$HOME") == 0)
>- instance_parent_dir = home;
>+ }
>+
>+ /*
>+ * Expand $HOME and $USER in instance dir prefix
>+ */
>+ if ((tptr = strstr(instance_prefix, "$USER")) != 0) {
>+ /* FIXME: should only support this if method is USER or BOTH */
>+ char *expanded = alloca(strlen(idata->user) + strlen(instance_prefix)-5+1);
>+ *tptr = 0;
>+ sprintf(expanded, "%s%s%s", instance_prefix, idata->user, tptr+5);
>+ instance_prefix = expanded;
>+ }
>+ if ((tptr = strstr(instance_prefix, "$HOME")) != 0) {
>+ char *expanded = alloca(strlen(home)+strlen(instance_prefix)-5+1);
>+ *tptr = 0;
>+ sprintf(expanded, "%s%s%s", instance_prefix, home, tptr+5);
>+ instance_prefix = expanded;
> }
>
> /*
> * Ensure that all pathnames are absolute path names.
> */
>- if ((dir[0] != '/') || (instance_parent_dir[0] != '/')) {
>+ if ((dir[0] != '/') || (instance_prefix[0] != '/')) {
> pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must start with '/'");
> return 0;
> }
>- if (strstr(dir, "..") || strstr(instance_parent_dir, "..")) {
>+ if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
> pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must not have '..'");
> return 0;
> }
>@@ -324,7 +331,7 @@
> * pathnames and the method with which to polyinstantiate.
> */
> strcpy(poly.dir, dir);
>- strcpy(poly.instance_parent_dir, instance_parent_dir);
>+ strcpy(poly.instance_prefix, instance_prefix);
> if (strcmp(method, "user") == 0)
> poly.method = USER;
> #ifdef WITH_SELINUX
>@@ -501,22 +508,12 @@
> struct instance_data *idata)
> #endif
> {
>- char *dir;
> #ifdef WITH_SELINUX
> security_context_t scon = NULL;
> security_class_t tclass;
> int rc;
> #endif
>
>- /*
>- * Get the last component of the pathname to polyinstantiate.
>- */
>- dir = strrchr(polyptr->dir, '/');
>- if (dir && (strlen(dir) > 1))
>- dir++;
>- else
>- dir = polyptr->dir;
>-
> # ifdef WITH_SELINUX
> /*
> * Get the security context of the directory to polyinstantiate.
>@@ -564,38 +561,20 @@
> */
> switch (polyptr->method) {
> case USER:
>- if (strcmp(polyptr->instance_parent_dir, "/") == 0) {
>- if (asprintf(i_name, "/.%s%s", idata->user, dir) < 0)
>- rc = PAM_SESSION_ERR;
>- } else {
>- if (asprintf(i_name, "%s/.%s%s", polyptr->instance_parent_dir,
>- idata->user, dir) < 0)
>- rc = PAM_SESSION_ERR;
>- }
>+ if (asprintf(i_name, "%s;%s", polyptr->dir, idata->user) < 0)
>+ rc = PAM_SESSION_ERR;
> break;
>
> #ifdef WITH_SELINUX
> case CONTEXT:
>- if (strcmp(polyptr->instance_parent_dir, "/") == 0) {
>- if (asprintf(i_name, "/.%s%s", *i_context, dir) < 0)
>- rc = PAM_SESSION_ERR;
>- } else {
>- if (asprintf(i_name, "%s/.%s%s", polyptr->instance_parent_dir,
>- *i_context, dir) < 0)
>- rc = PAM_SESSION_ERR;
>- }
>+ if (asprintf(i_name, "%s;%s", polyptr->dir, *i_context) < 0)
>+ rc = PAM_SESSION_ERR;
> break;
>
> case BOTH:
>- if (strcmp(polyptr->instance_parent_dir, "/") == 0) {
>- if (asprintf(i_name, "/.%s%s%s", *i_context,
>- idata->user, dir) < 0)
>- rc = PAM_SESSION_ERR;
>- } else {
>- if (asprintf(i_name, "%s/.%s%s%s", polyptr->instance_parent_dir,
>- *i_context, idata->user, dir) < 0)
>- rc = PAM_SESSION_ERR;
>- }
>+ if (asprintf(i_name, "%s;%s;%s", polyptr->dir,
>+ *i_context, idata->user) < 0)
>+ rc = PAM_SESSION_ERR;
> break;
> #endif /* WITH_SELINUX */
>
>@@ -733,14 +712,13 @@
> struct instance_data *idata)
> {
> int i, retval = 0;
>- char *inst_parent_dir = NULL;
>+ char *inst_dir = NULL;
> char *md5inst = NULL, *instname = NULL;
>- char *to, *dir, *lastchr;
>+ char *to, *dir;
> #ifdef WITH_SELINUX
> security_context_t instcontext = NULL, origcontext = NULL;
> #endif
> unsigned char inst_digest[MD5_DIGEST_LENGTH];
>- int username = (polyptr->method == USER) || (polyptr->method == BOTH);
>
> if (idata->debug)
> pam_syslog(idata->pamh, LOG_NOTICE,
>@@ -793,13 +771,6 @@
> goto error_out;
> }
>
>- /*
>- * In the case where instance path is just / or has a trailing,
>- * we should not include an extra / in the asprintfs below. It messes
>- * up when we are trying to unmount the filesystem based on
>- * /proc/mounts
>- */
>-
> to = md5inst;
> for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
> char c[3];
>@@ -807,33 +778,22 @@
> to = stpcpy(to, c);
> }
>
>- lastchr = polyptr->instance_parent_dir +
>- strlen(polyptr->instance_parent_dir) - 1;
>- if (*lastchr == '/') {
>- if (asprintf(&inst_parent_dir, "%s.inst-%s-%s",
>- polyptr->instance_parent_dir, username ? idata->user : "",
>- md5inst) < 0)
>- goto error_out;
>- } else {
>- if (asprintf(&inst_parent_dir, "%s/.inst-%s-%s",
>- polyptr->instance_parent_dir, username ? idata->user : "",
>- md5inst) < 0)
>- goto error_out;
>- }
>+ if (asprintf(&inst_dir, "%s%s", polyptr->instance_prefix, md5inst) < 0)
>+ goto error_out;
>
> if (idata->debug)
>- pam_syslog(idata->pamh, LOG_NOTICE, "instance_parent_dir %s",
>- inst_parent_dir);
>+ pam_syslog(idata->pamh, LOG_NOTICE, "instance_dir %s",
>+ inst_dir);
>
> /*
> * Create instance directory with appropriate security
> * contexts, owner, group and mode bits.
> */
> #ifdef WITH_SELINUX
>- retval = create_dirs(polyptr, inst_parent_dir, instcontext,
>+ retval = create_dirs(polyptr, inst_dir, instcontext,
> origcontext, idata);
> #else
>- retval = create_dirs(polyptr, inst_parent_dir, idata);
>+ retval = create_dirs(polyptr, inst_dir, idata);
> #endif
>
> if (retval < 0) {
>@@ -843,13 +803,13 @@
> }
>
> /*
>- * Bind mount instance parent directory on top of the polyinstantiated
>+ * Bind mount instance directory on top of the polyinstantiated
> * directory to provide an instance of polyinstantiated directory
> * based on polyinstantiated method.
> */
>- if (mount(inst_parent_dir, polyptr->dir, NULL, MS_BIND, NULL) < 0) {
>+ if (mount(inst_dir, polyptr->dir, NULL, MS_BIND, NULL) < 0) {
> pam_syslog(idata->pamh, LOG_ERR, "Error mounting %s on %s, %s",
>- inst_parent_dir, polyptr->dir, strerror(errno));
>+ inst_dir, polyptr->dir, strerror(errno));
> goto error_out;
> }
>
>@@ -864,7 +824,7 @@
>
> cleanup:
> free(md5inst);
>- free(inst_parent_dir);
>+ free(inst_dir);
> free(instname);
> #ifdef WITH_SELINUX
> freecon(instcontext);
>@@ -1022,7 +982,7 @@
>
> /*
> * Orig namespace. This function is called from when closing a pam
>- * session. If authorized, it unmounts instance_parent directory.
>+ * session. If authorized, it unmounts instance directory.
> */
> static int orig_namespace(struct instance_data *idata)
> {
>@@ -1036,7 +996,7 @@
> * Cycle through all polyinstantiated directories from the namespace
> * configuration file to see if polyinstantiation was performed for
> * this user for each of the entry. If it was, try and unmount
>- * appropriate polyinstantiated instance parent directories.
>+ * appropriate polyinstantiated instance directories.
> */
> for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) {
> if (ns_override(pptr, idata))
>@@ -1044,7 +1004,7 @@
> else {
> if (idata->debug)
> pam_syslog(idata->pamh, LOG_NOTICE,
>- "Unmounting instance parent dir for user %d & dir %s",
>+ "Unmounting instance dir for user %d & dir %s",
> idata->uid, pptr->dir);
>
> if (umount(pptr->dir) < 0) {
>diff -ur Janak/README ./README
>--- Janak/README 2006-02-17 02:34:28.000000000 -0600
>+++ ./README 2006-02-17 03:15:34.000000000 -0600
>@@ -9,47 +9,47 @@
> installed by default provides example for polyinstantiating /tmp
> and users' home directory.
>
>-Each line describes a limit for a user in the form:
>+Each line in namespace.conf describes a limit for a user in the form:
>
>-<polydir> <instance_parent_dir> <method> <list_of_uids>
>+<polydir> <instance_prefix> <method> <list_of_uids>
>
> Where:
> <polydir> - is the absolute pathname of the directory to polyinstantiate
>- Special entry $HOME is supported to designate user's home directory.
>- This field cannot be blank.
>+ Special entry $HOME is supported to designate user's home directory.
>+ This field cannot be blank.
>
>-<instance_parent_dir> - is the absolute pathname of the parent directory
>- where an instantiation of <polydir> is to be created. This
>- instance is bind mounted on the <polydir> to provide an instance
>- of <polydir> based on the <method> column. Two special entries
>- $HOME and $HOME_PARENT are supported to designate user's home
>- directory and parent of user's home directory. This field cannot
>- be blank.
>+<instance_prefix> - is the string prefix used to build the pathname for the
>+ instantiation of <polydir>. A md5sum string (32 hex characters) is appended
>+ to the prefix to generate the final instance directory path. This
>+ directory is created if it did not exist already, and is then
>+ bind mounted on the <polydir> to provide an instance of <polydir>
>+ based on the <method> column. The special string $HOME is replaced with
>+ the user's home directory, and $USER with the username.
>+ This field cannot be blank.
>
> <method> - is the method used for polyinstantiation. It can take 3 different
> values; "user" for polyinstantiation based on user name, "context"
> for polyinstantiation based on process security context, and "both"
> for polyinstantiation based on both user name and security context.
> Methods "context" and "both" are only available with SELinux. This
>- field cannot be blank.
>+ field cannot be blank.
>
> <list_of_uids> - is a comma separated list of user names for whom the
>- poyinstantiation is not performed. If left blank, polyinstantiation
>+ polyinstantiation is not performed. If left blank, polyinstantiation
> will be performed for all users.
>
> EXAMPLE /etc/security/namespace.conf configuration file:
> =======================================================
>-# comments
>-#
> # Following two lines will polyinstantiate /tmp directory and user's home
> # directory. /tmp will be polyinstantiated based on both security context
> # as well as user name, where as home directory will be polyinstantiated
> # based on security context only. Polyinstantion will not be performed
> # for user root and adm for directory /tmp, where as home directories
> # are polyinstantiated for all users.
>-/tmp / both root,adm
>-$HOME $HOME_PARENT $HOME_PARENT context
>-
>+#
>+# /tmp /tmp.inst-$USER- both root,adm
>+# /var/tmp /var/tmp.inst-$USER- both root,adm
>+# $HOME $HOME.inst- context
>
> ARGUMENTS RECOGNIZED:
> debug Verbose logging by syslog
>
>--
>redhat-lspp mailing list
>redhat-lspp at redhat.com
>https://www.redhat.com/mailman/listinfo/redhat-lspp
>
>
>
>
More information about the redhat-lspp
mailing list