[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