rpms/pam/devel pam-0.99.6.2-namespace-docfix.patch, NONE, 1.1 pam-0.99.6.2-namespace-temp-logon.patch, NONE, 1.1 pam-0.99.7.1-unix-hpux-aging.patch, NONE, 1.1 pam-0.99.7.1-unix-update-helper.patch, NONE, 1.1 pam-0.99.7.1-unix-bigcrypt.patch, 1.1, 1.2 pam.spec, 1.146, 1.147 pam-0.78-unix-hpux-aging.patch, 1.1, NONE

Tomas Mraz (tmraz) fedora-extras-commits at redhat.com
Mon Jun 4 14:23:00 UTC 2007


Author: tmraz

Update of /cvs/extras/rpms/pam/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv29828

Modified Files:
	pam-0.99.7.1-unix-bigcrypt.patch pam.spec 
Added Files:
	pam-0.99.6.2-namespace-docfix.patch 
	pam-0.99.6.2-namespace-temp-logon.patch 
	pam-0.99.7.1-unix-hpux-aging.patch 
	pam-0.99.7.1-unix-update-helper.patch 
Removed Files:
	pam-0.78-unix-hpux-aging.patch 
Log Message:
* Thu Apr 26 2007 Tomas Mraz <tmraz at redhat.com> 0.99.7.1-6
- pam_namespace: better document behavior on failure (#237249)
- pam_unix: split out passwd change to a new helper binary (#236316)
- pam_namespace: add support for temporary logons (#241226)


pam-0.99.6.2-namespace-docfix.patch:

--- NEW FILE pam-0.99.6.2-namespace-docfix.patch ---
--- Linux-PAM-0.99.6.2/modules/pam_namespace/namespace.conf.5.xml.docfix	2007-04-03 17:51:29.000000000 +0200
+++ Linux-PAM-0.99.6.2/modules/pam_namespace/namespace.conf.5.xml	2007-04-23 19:04:10.000000000 +0200
@@ -86,6 +86,15 @@
       for all users.
     </para>
 
+    <para>
+      In case of context or level polyinstantiation the SELinux context
+      which is used for polyinstantiation is the context used for executing
+      a new process as obtained by getexeccon. This context must be set
+      by the calling application or <filename>pam_selinux.so</filename>
+      module. If this context is not set the polyinstatiation will be
+      based just on user name.
+    </para>
+
   </refsect1>
 
   <refsect1 id="namespace.conf-examples">

pam-0.99.6.2-namespace-temp-logon.patch:

--- NEW FILE pam-0.99.6.2-namespace-temp-logon.patch ---
--- Linux-PAM-0.99.6.2/modules/pam_namespace/pam_namespace.h.temp-logon	2007-05-31 17:04:17.000000000 +0200
+++ Linux-PAM-0.99.6.2/modules/pam_namespace/pam_namespace.h	2007-05-31 17:04:18.000000000 +0200
@@ -90,6 +90,7 @@
 #define PAMNS_NO_UNMOUNT_ON_CLOSE  0x00010000 /* no unmount at session close */
 
 #define NAMESPACE_MAX_DIR_LEN 80
+#define NAMESPACE_POLYDIR_DATA "pam_namespace:polydir_data"
 
 /*
  * Polyinstantiation method options, based on user, security context
@@ -100,6 +101,8 @@
     USER,
     CONTEXT,
     LEVEL,
+    TMPDIR,
+    TMPFS
 };
 
 /*
@@ -128,6 +131,7 @@
     enum polymethod method;		/* method used to polyinstantiate */
     unsigned int num_uids;		/* number of override uids */
     uid_t *uid;				/* list of override uids */
+    int exclusive;			/* polyinstatiate exclusively for override uids */
     struct polydir_s *next;		/* pointer to the next polydir entry */
 };
 
--- Linux-PAM-0.99.6.2/modules/pam_namespace/pam_namespace.c.temp-logon	2007-05-31 17:04:18.000000000 +0200
+++ Linux-PAM-0.99.6.2/modules/pam_namespace/pam_namespace.c	2007-05-31 17:54:14.000000000 +0200
@@ -43,6 +43,7 @@
 	strcpy(pent->instance_prefix, ent->instance_prefix);
 	pent->method = ent->method;
 	pent->num_uids = ent->num_uids;
+	pent->exclusive = ent->exclusive;
 	if (ent->num_uids) {
 		uid_t *pptr, *eptr;
 
@@ -120,6 +121,10 @@
 	}
 }
 
+static void cleanup_data(pam_handle_t *pamh, void *data, int err)
+{
+	del_polydir_list(data);
+}
 
 /*
  * Called from parse_config_file, this function processes a single line
@@ -140,6 +145,7 @@
 
     poly.uid = NULL;
     poly.num_uids = 0;
+    poly.exclusive = 0;
 
     /*
      * skip the leading white space
@@ -223,24 +229,13 @@
     }
 
     /*
-     * Ensure that all pathnames are absolute path names.
-     */
-    if ((dir[0] != '/') || (instance_prefix[0] != '/')) {
-        pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must start with '/'");
-        goto skipping;
-    }
-    if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
-        pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must not contain '..'");
-        goto skipping;
-    }
-
-    /*
      * Populate polyinstantiated directory structure with appropriate
      * pathnames and the method with which to polyinstantiate.
      */
     if (strlen(dir) >= sizeof(poly.dir)
 	|| strlen(instance_prefix) >= sizeof(poly.instance_prefix)) {
 	pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
+	goto skipping;
     }
     strcpy(poly.dir, dir);
     strcpy(poly.instance_prefix, instance_prefix);
@@ -248,6 +243,18 @@
     poly.method = NONE;
     if (strcmp(method, "user") == 0) 
 	    poly.method = USER;
+    
+    if (strcmp(method, "tmpdir") == 0) {
+    	    poly.method = TMPDIR;
+    	    if (sizeof(poly.instance_prefix) - strlen(poly.instance_prefix) < 7) {
+    		pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
+    		goto skipping;
+    	    }
+    	    strcat(poly.instance_prefix, "XXXXXX");
+    }
+    
+    if (strcmp(method, "tmpfs") == 0)
+            poly.method = TMPFS;
 
 #ifdef WITH_SELINUX
     if (strcmp(method, "level") == 0) {
@@ -266,12 +273,24 @@
 
 #endif
 
-    if ( poly.method == NONE) {
+    if (poly.method == NONE) {
         pam_syslog(idata->pamh, LOG_NOTICE, "Illegal method");
         goto skipping;
     }
 
     /*
+     * Ensure that all pathnames are absolute path names.
+     */
+    if ((dir[0] != '/') || (poly.method != TMPFS && instance_prefix[0] != '/')) {
+        pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must start with '/'");
+        goto skipping;
+    }
+    if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
+        pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must not contain '..'");
+        goto skipping;
+    }
+
+    /*
      * If the line in namespace.conf for a directory to polyinstantiate
      * contains a list of override users (users for whom polyinstantiation
      * is not performed), read the user ids, convert names into uids, and
@@ -281,7 +300,11 @@
         uid_t *uidptr;
         const char *ustr, *sstr;
         int count, i;
-
+	
+	if (*uids == '~') {
+		poly.exclusive = 1;
+		uids++;
+	}
         for (count = 0, ustr = sstr = uids; sstr; ustr = sstr + 1, count++)
            sstr = strchr(ustr, ',');
 
@@ -419,6 +442,7 @@
  * directory's list of override uids. If the uid is one of the override
  * uids for the polyinstantiated directory, polyinstantiation is not
  * performed for that user for that directory.
+ * If exclusive is set the returned values are opposite.
  */
 static int ns_override(struct polydir_s *polyptr, struct instance_data *idata,
 		uid_t uid)
@@ -432,11 +456,11 @@
 
     for (i = 0; i < polyptr->num_uids; i++) {
         if (uid == polyptr->uid[i]) {
-            return 1;
+            return !polyptr->exclusive;
         }
     }
 
-    return 0;
+    return polyptr->exclusive;
 }
 
 /*
@@ -622,6 +646,12 @@
 
 #endif /* WITH_SELINUX */
 
+	case TMPDIR:
+	case TMPFS:
+	    if ((*i_name=strdup("")) == NULL)
+	    	goto fail;
+	    return PAM_SUCCESS;
+
     	default:
     	    if (idata->flags & PAMNS_DEBUG)
     	        pam_syslog(idata->pamh, LOG_ERR, "Unknown method");
@@ -725,7 +755,7 @@
 * execute it and pass directory to polyinstantiate and instance
 * directory as arguments.
 */
-static int inst_init(const struct polydir_s *polyptr, char *ipath,  
+static int inst_init(const struct polydir_s *polyptr, const char *ipath,
 	   struct instance_data *idata)
 {
 	pid_t rc, pid;
@@ -791,11 +821,11 @@
  * Create polyinstantiated instance directory (ipath).
  */
 #ifdef WITH_SELINUX
-static int create_dirs(const struct polydir_s *polyptr, char *ipath, 
+static int create_dirs(struct polydir_s *polyptr, char *ipath, 
         security_context_t icontext, security_context_t ocontext,
 	struct instance_data *idata)
 #else
-static int create_dirs(const struct polydir_s *polyptr, char *ipath,
+static int create_dirs(struct polydir_s *polyptr, char *ipath,
 	struct instance_data *idata)
 #endif
 {
@@ -834,7 +864,17 @@
      * attributes to match that of the original directory that is being
      * polyinstantiated.
      */
-    if (mkdir(ipath, S_IRUSR) < 0) {
+    
+    if (polyptr->method == TMPDIR) {
+    	if (mkdtemp(polyptr->instance_prefix) == NULL) {
+            pam_syslog(idata->pamh, LOG_ERR, "Error creating temporary instance %s, %m",
+			polyptr->instance_prefix);
+	    polyptr->method = NONE; /* do not clean up! */
+	    return PAM_SESSION_ERR;
+    	}
+	/* copy the actual directory name to ipath */
+	strcpy(ipath, polyptr->instance_prefix);
+    } else if (mkdir(ipath, S_IRUSR) < 0) {
         if (errno == EEXIST)
             goto inst_init;
         else {
@@ -920,13 +960,12 @@
  * security attributes, and performs bind mount to setup the process
  * namespace.
  */
-static int ns_setup(const struct polydir_s *polyptr,
+static int ns_setup(struct polydir_s *polyptr,
 	struct instance_data *idata)
 {
     int retval = 0;
     char *inst_dir = NULL;
     char *instname = NULL;
-    char *dir;
 #ifdef WITH_SELINUX
     security_context_t instcontext = NULL, origcontext = NULL;
 #endif
@@ -935,9 +974,15 @@
         pam_syslog(idata->pamh, LOG_DEBUG,
                "Set namespace for directory %s", polyptr->dir);
 
-    dir = strrchr(polyptr->dir, '/');
-    if (dir && strlen(dir) > 1)
-        dir++;
+    if (polyptr->method == TMPFS) {
+	if (mount("tmpfs", polyptr->dir, "tmpfs", 0, NULL) < 0) {
+	    pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m",
+        	polyptr->dir);
+            return PAM_SESSION_ERR;
+	}
+	/* we must call inst_init after the mount in this case */
+	return inst_init(polyptr, "tmpfs", idata);
+    }
 
     /*
      * Obtain the name of instance pathname based on the
@@ -1043,6 +1088,58 @@
     return retval;
 }
 
+static int cleanup_tmpdirs(struct instance_data *idata)
+{
+    struct polydir_s *pptr;
+    pid_t rc, pid;
+    sighandler_t osighand = NULL;
+    int status;
+
+    osighand = signal(SIGCHLD, SIG_DFL);
+    if (osighand == SIG_ERR) {
+	pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
+	rc = PAM_SESSION_ERR;
+	goto out;
+    }
+
+    for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) {
+	if (pptr->method == TMPDIR && access(pptr->instance_prefix, F_OK) == 0) {
+	    pid = fork();
+	    if (pid == 0) {
+#ifdef WITH_SELINUX
+		if (idata->flags & PAMNS_SELINUX_ENABLED) {
+		    if (setexeccon(NULL) < 0)
+			exit(1);
+		}
+#endif
+		if (execl("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, (char *)NULL) < 0)
+			exit(1);
+	    } else if (pid > 0) {
+		while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
+		    (errno == EINTR));
+		if (rc == (pid_t)-1) {
+		    pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m");
+		    rc = PAM_SESSION_ERR;
+		    goto out;
+		}
+		if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) {
+		    pam_syslog(idata->pamh, LOG_ERR,
+		    	"Error removing %s", pptr->instance_prefix);
+		}
+	    } else if (pid < 0) {
+		pam_syslog(idata->pamh, LOG_ERR,
+			"Cannot fork to run namespace init script, %m");
+		rc = PAM_SESSION_ERR;
+		goto out;
+	    }
+        }
+    }
+
+    rc = PAM_SUCCESS;
+out:
+    signal(SIGCHLD, osighand);
+    return rc;
+}
 
 /*
  * This function checks to see if polyinstantiation is needed for any
@@ -1111,13 +1208,22 @@
      * disassociate from the parent namespace.
      */
     if (need_poly) {
+	if (pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, idata->polydirs_ptr,
+    		cleanup_data) != PAM_SUCCESS) {
+    	    pam_syslog(idata->pamh, LOG_ERR,
+    	    	"Unable to set namespace data");
+    	    return PAM_SYSTEM_ERR;
+    	}
         if (unshare(CLONE_NEWNS) < 0) {
-            pam_syslog(idata->pamh, LOG_ERR,
+		pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
+		pam_syslog(idata->pamh, LOG_ERR,
 		"Unable to unshare from parent namespace, %m");
             return PAM_SESSION_ERR;
         }
-    } else
+    } else {
+    	del_polydir_list(idata->polydirs_ptr);
         return PAM_SUCCESS;
+    }
 
     /*
      * Again cycle through all polyinstantiated directories, this time,
@@ -1144,7 +1250,8 @@
                  * umount
                  */
                 if ((changing_dir = cwd_in(pptr->dir, idata)) < 0) {
-                    return PAM_SESSION_ERR;
+                    retval = PAM_SESSION_ERR;
+                    goto out;
                 } else if (changing_dir) {
                     if (idata->flags & PAMNS_DEBUG)
                         pam_syslog(idata->pamh, LOG_DEBUG, "changing cwd");
@@ -1172,8 +1279,10 @@
             	    int saved_errno = errno;
             	    pam_syslog(idata->pamh, LOG_ERR, "Unmount of %s failed, %m",
                     	pptr->dir);
-            	    if (saved_errno != EINVAL)
-                	return PAM_SESSION_ERR;
+            	    if (saved_errno != EINVAL) {
+                	retval = PAM_SESSION_ERR;
+                	goto out;
+                    }
                 } else if (idata->flags & PAMNS_DEBUG)
                     pam_syslog(idata->pamh, LOG_DEBUG, "Umount succeeded %s",
 				pptr->dir);
@@ -1185,7 +1294,9 @@
                      break;
 	}
     }
-
+out:
+    if (retval != PAM_SUCCESS)
+    	cleanup_tmpdirs(idata);
     return retval;
 }
 
@@ -1224,8 +1335,10 @@
             } else if (idata->flags & PAMNS_DEBUG)
                 pam_syslog(idata->pamh, LOG_DEBUG, "Unmount of %s succeeded",
 			pptr->dir);
-        }
+	}
     }
+
+    cleanup_tmpdirs(idata);
     return 0;
 }
 
@@ -1349,7 +1462,8 @@
     } else if (idata.flags & PAMNS_DEBUG)
         pam_syslog(idata.pamh, LOG_DEBUG, "Nothing to polyinstantiate");
 
-    del_polydir_list(idata.polydirs_ptr);
+    if (retval != PAM_SUCCESS)
+	del_polydir_list(idata.polydirs_ptr);
     return retval;
 }
 
@@ -1364,6 +1478,7 @@
     struct instance_data idata;
     char *user_name;
     struct passwd *pwd;
+    const void *polyptr;
 
     /* init instance data */
     idata.flags = 0;
@@ -1425,16 +1540,12 @@
     idata.user = user_name;
     idata.uid = pwd->pw_uid;
 
-    /*
-     * Parse namespace configuration file which lists directories that
-     * are polyinstantiated, directories where instance directories are
-     * created and the method used for polyinstantiation.
-     */
-    retval = parse_config_file(&idata);
-    if ((retval != PAM_SUCCESS) || !idata.polydirs_ptr) {
-	del_polydir_list(idata.polydirs_ptr);
-        return PAM_SESSION_ERR;
-    }
+    retval = pam_get_data(idata.pamh, NAMESPACE_POLYDIR_DATA, &polyptr);
+    if (retval != PAM_SUCCESS || polyptr == NULL)
+    	/* nothing to reset */
+    	return PAM_SUCCESS;
+    	
+    idata.polydirs_ptr = polyptr;
 
     if (idata.flags & PAMNS_DEBUG)
         pam_syslog(idata.pamh, LOG_DEBUG, "Resetting namespace for pid %d",
@@ -1449,7 +1560,9 @@
             pam_syslog(idata.pamh, LOG_DEBUG, 
 		"resetting namespace ok for pid %d", getpid());
     }
-    del_polydir_list(idata.polydirs_ptr);
+
+    pam_set_data(idata.pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
+    
     return PAM_SUCCESS;
 }
 

pam-0.99.7.1-unix-hpux-aging.patch:

--- NEW FILE pam-0.99.7.1-unix-hpux-aging.patch ---
o For non-extensible-style hashes, strip off anything after the 13th character
  which would not be valid as part of a hash.  On HP/UX, this clips off a comma
  followed by encoded aging information.

  The real problem is a complete lack of any standard for storing password
  aging information (actually, for anything having to do with password aging)
  for users across operating systems, but there's nothing we can do about that
  here.

--- Linux-PAM-0.99.7.1/modules/pam_unix/support.c.unix-hpux-aging	2007-06-01 15:21:08.000000000 +0200
+++ Linux-PAM-0.99.7.1/modules/pam_unix/support.c	2007-06-01 15:24:32.000000000 +0200
@@ -573,6 +573,21 @@
     return retval;
 }
 
+static void strip_hpux_aging(char *p)
+{
+	const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+			    "abcdefghijklmnopqrstuvwxyz"
+			    "0123456789./";
+	if ((*p != '$') && (strlen(p) > 13)) {
+		for (p += 13; *p != '\0'; p++) {
+			if (strchr(valid, *p) == NULL) {
+				*p = '\0';
+				break;
+			}
+		}
+	}
+}
+
 int _unix_verify_password(pam_handle_t * pamh, const char *name
 			  ,const char *p, unsigned int ctrl)
 {
@@ -679,7 +694,9 @@
 			}
 		}
 	} else {
-	    size_t salt_len = strlen(salt);
+	    size_t salt_len;
+	    strip_hpux_aging(salt);
+	    salt_len = strlen(salt);
 	    if (!salt_len) {
 		/* the stored password is NULL */
 		if (off(UNIX__NONULL, ctrl)) {/* this means we've succeeded */
--- Linux-PAM-0.99.7.1/modules/pam_unix/passverify.c.unix-hpux-aging	2007-06-01 15:21:08.000000000 +0200
+++ Linux-PAM-0.99.7.1/modules/pam_unix/passverify.c	2007-06-01 15:26:26.000000000 +0200
@@ -146,6 +146,22 @@
 	return i;
 }
 
+static void
+strip_hpux_aging(char *p)
+{
+	const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+			    "abcdefghijklmnopqrstuvwxyz"
+			    "0123456789./";
+	if ((*p != '$') && (strlen(p) > 13)) {
+		for (p += 13; *p != '\0'; p++) {
+			if (strchr(valid, *p) == NULL) {
+				*p = '\0';
+				break;
+			}
+		}
+	}
+}
+
 int
 _unix_verify_password(const char *name, const char *p, int nullok)
 {
@@ -194,6 +210,7 @@
 		return PAM_USER_UNKNOWN;
 	}
 
+	strip_hpux_aging(salt);
 	salt_len = strlen(salt);
 	if (salt_len == 0) {
 		return (nullok == 0) ? PAM_AUTH_ERR : PAM_SUCCESS;

pam-0.99.7.1-unix-update-helper.patch:

--- NEW FILE pam-0.99.7.1-unix-update-helper.patch ---
--- /dev/null	2007-05-28 11:10:34.936447748 +0200
+++ Linux-PAM-0.99.7.1/modules/pam_unix/passupdate.c	2007-06-01 15:13:57.000000000 +0200
@@ -0,0 +1,560 @@
+/*
+ * Main coding by Elliot Lee <sopwith at redhat.com>, Red Hat Software.
+ * Copyright (C) 1996.
+ * Copyright (c) Jan Rêkorajski, 1999.
+ * Copyright (c) Red Hat, Inc., 2007
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* this will be included from module and update helper */
+
+#if defined(USE_LCKPWDF) && !defined(HAVE_LCKPWDF)
+# include "./lckpwdf.-c"
+#endif
+
+/* passwd/salt conversion macros */
+
+#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.')
+#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
+
+#define PW_TMPFILE		"/etc/npasswd"
+#define SH_TMPFILE		"/etc/nshadow"
+#define OPW_TMPFILE		"/etc/security/nopasswd"
+#define OLD_PASSWORDS_FILE	"/etc/security/opasswd"
+
+/*
+ * i64c - convert an integer to a radix 64 character
+ */
+static int i64c(int i)
+{
+	if (i < 0)
+		return ('.');
+	else if (i > 63)
+		return ('z');
+	if (i == 0)
+		return ('.');
+	if (i == 1)
+		return ('/');
+	if (i >= 2 && i <= 11)
+		return ('0' - 2 + i);
+	if (i >= 12 && i <= 37)
+		return ('A' - 12 + i);
+	if (i >= 38 && i <= 63)
+		return ('a' - 38 + i);
+	return ('\0');
+}
+
+static char *crypt_md5_wrapper(const char *pass_new)
+{
+	/*
+	 * Code lifted from Marek Michalkiewicz's shadow suite. (CG)
+	 * removed use of static variables (AGM)
+	 */
+
+	struct timeval tv;
+	MD5_CTX ctx;
+	unsigned char result[16];
+	char *cp = (char *) result;
+	unsigned char tmp[16];
+	int i;
+	char *x = NULL;
+
+	GoodMD5Init(&ctx);
+	gettimeofday(&tv, (struct timezone *) 0);
+	GoodMD5Update(&ctx, (void *) &tv, sizeof tv);
+	i = getpid();
+	GoodMD5Update(&ctx, (void *) &i, sizeof i);
+	i = clock();
+	GoodMD5Update(&ctx, (void *) &i, sizeof i);
+	GoodMD5Update(&ctx, result, sizeof result);
+	GoodMD5Final(tmp, &ctx);
+	strcpy(cp, "$1$");	/* magic for the MD5 */
+	cp += strlen(cp);
+	for (i = 0; i < 8; i++)
+		*cp++ = i64c(tmp[i] & 077);
+	*cp = '\0';
+
+	/* no longer need cleartext */
+	x = Goodcrypt_md5(pass_new, (const char *) result);
+
+	return x;
+}
+
+#ifdef USE_LCKPWDF
+static int lock_pwdf(void)
+{
+	int i;
+	int retval;
+
+#ifndef HELPER_COMPILE
+	if (selinux_confined()) {
+		return PAM_SUCCESS;
+	}
+#endif
+	/* These values for the number of attempts and the sleep time
+	   are, of course, completely arbitrary.
+	   My reading of the PAM docs is that, once pam_chauthtok() has been
+	   called with PAM_UPDATE_AUTHTOK, we are obliged to take any
+	   reasonable steps to make sure the token is updated; so retrying
+	   for 1/10 sec. isn't overdoing it. */
+	i=0;
+	while((retval = lckpwdf()) != 0 && i < 100) {
+		usleep(1000);
+		i++;
+	}
+	if(retval != 0) {
+		return PAM_AUTHTOK_LOCK_BUSY;
+	}
+	return PAM_SUCCESS;
+}
+
+static void unlock_pwdf(void)
+{
+#ifndef HELPER_COMPILE
+	if (selinux_confined()) {
+		return;
+	}
+#endif
+	ulckpwdf();
+}
+#endif
+
+static int
+save_old_password(const char *forwho, const char *oldpass,
+		  int howmany)
+{
+    static char buf[16384];
+    static char nbuf[16384];
+    char *s_luser, *s_uid, *s_npas, *s_pas, *pass;
+    int npas;
+    FILE *pwfile, *opwfile;
+    int err = 0;
+    int oldmask;
+    int found = 0;
+    struct passwd *pwd = NULL;
+    struct stat st;
+
+    if (howmany < 0) {
+	return PAM_SUCCESS;
+    }
+
+    if (oldpass == NULL) {
+	return PAM_SUCCESS;
+    }
+
+    oldmask = umask(077);
+
+#ifdef WITH_SELINUX
+    if (SELINUX_ENABLED) {
+      security_context_t passwd_context=NULL;
+      if (getfilecon("/etc/passwd",&passwd_context)<0) {
+        return PAM_AUTHTOK_ERR;
+      };
+      if (getfscreatecon(&prev_context)<0) {
+        freecon(passwd_context);
+        return PAM_AUTHTOK_ERR;
+      }
+      if (setfscreatecon(passwd_context)) {
+        freecon(passwd_context);
+        freecon(prev_context);
+        return PAM_AUTHTOK_ERR;
+      }
+      freecon(passwd_context);
+    }
+#endif
+    pwfile = fopen(OPW_TMPFILE, "w");
+    umask(oldmask);
[...2149 lines suppressed...]
+{
+	struct passwd *pwd = NULL;
+	struct spwd *spwdent = NULL;
+	char *salt = NULL;
+	char *pp = NULL;
+	int retval = PAM_AUTH_ERR;
+	size_t salt_len;
+
+	/* UNIX passwords area */
+	setpwent();
+	pwd = getpwnam(name);	/* Get password file entry... */
+	endpwent();
+	if (pwd != NULL) {
+		if (_unix_shadowed(pwd)) {
+			/*
+			 * ...and shadow password file entry for this user,
+			 * if shadowing is enabled
+			 */
+			setspent();
+			spwdent = getspnam(name);
+			endspent();
+			if (spwdent != NULL)
+				salt = x_strdup(spwdent->sp_pwdp);
+			else
+				pwd = NULL;
+		} else {
+			if (strcmp(pwd->pw_passwd, "*NP*") == 0) {	/* NIS+ */
+				uid_t save_uid;
+
+				save_uid = geteuid();
+				seteuid(pwd->pw_uid);
+				spwdent = getspnam(name);
+				seteuid(save_uid);
+
+				salt = x_strdup(spwdent->sp_pwdp);
+			} else {
+				salt = x_strdup(pwd->pw_passwd);
+			}
+		}
+	}
+	if (pwd == NULL || salt == NULL) {
+		_log_err(LOG_ALERT, "check pass; user unknown");
+		p = NULL;
+		return PAM_USER_UNKNOWN;
+	}
+
+	salt_len = strlen(salt);
+	if (salt_len == 0) {
+		return (nullok == 0) ? PAM_AUTH_ERR : PAM_SUCCESS;
+	}
+	if (p == NULL || strlen(p) == 0) {
+		_pam_overwrite(salt);
+		_pam_drop(salt);
+		return PAM_AUTHTOK_ERR;
+	}
+
+	/* the moment of truth -- do we agree with the password? */
+	retval = PAM_AUTH_ERR;
+	if (!strncmp(salt, "$1$", 3)) {
+		pp = Goodcrypt_md5(p, salt);
+		if (pp && strcmp(pp, salt) == 0) {
+			retval = PAM_SUCCESS;
+		} else {
+			_pam_overwrite(pp);
+			_pam_drop(pp);
+			pp = Brokencrypt_md5(p, salt);
+			if (pp && strcmp(pp, salt) == 0)
+				retval = PAM_SUCCESS;
+		}
+	} else if (*salt == '$') {
+	        /*
+		 * Ok, we don't know the crypt algorithm, but maybe
+		 * libcrypt nows about it? We should try it.
+		 */
+	        pp = x_strdup (crypt(p, salt));
+		if (pp && strcmp(pp, salt) == 0) {
+			retval = PAM_SUCCESS;
+		}
+	} else if (*salt == '*' || *salt == '!' || salt_len < 13) {
+	    retval = PAM_AUTH_ERR;
+	} else {
+		pp = bigcrypt(p, salt);
+		/*
+		 * Note, we are comparing the bigcrypt of the password with
+		 * the contents of the password field. If the latter was
+		 * encrypted with regular crypt (and not bigcrypt) it will
+		 * have been truncated for storage relative to the output
+		 * of bigcrypt here. As such we need to compare only the
+		 * stored string with the subset of bigcrypt's result.
+		 * Bug 521314.
+		 */
+		if (pp && salt_len == 13 && strlen(pp) > salt_len) {
+		    _pam_overwrite(pp+salt_len);
+		}
+		
+		if (pp && strcmp(pp, salt) == 0) {
+			retval = PAM_SUCCESS;
+		}
+	}
+	p = NULL;		/* no longer needed here */
+
+	/* clean up */
+	_pam_overwrite(pp);
+	_pam_drop(pp);
+
+	return retval;
+}
+
+char *
+getuidname(uid_t uid)
+{
+	struct passwd *pw;
+	static char username[256];
+
+	pw = getpwuid(uid);
+	if (pw == NULL)
+		return NULL;
+
+	strncpy(username, pw->pw_name, sizeof(username));
+	username[sizeof(username) - 1] = '\0';
+
+	return username;
+}
+/*
+ * Copyright (c) Andrew G. Morgan, 1996. All rights reserved
+ * Copyright (c) Red Hat, Inc. 2007. All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
--- Linux-PAM-0.99.7.1/modules/pam_unix/Makefile.am.update-helper	2006-12-18 19:50:50.000000000 +0100
+++ Linux-PAM-0.99.7.1/modules/pam_unix/Makefile.am	2007-06-01 15:15:04.000000000 +0200
@@ -16,7 +16,8 @@
 secureconfdir = $(SCONFIGDIR)
 
 AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-	-DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\"
+	-DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\" \
+	-DUPDATE_HELPER=\"$(sbindir)/unix_update\"
 
 if HAVE_LIBSELINUX
   AM_CFLAGS += -D"WITH_SELINUX"
@@ -34,9 +35,9 @@
 
 securelib_LTLIBRARIES = pam_unix.la
 
-noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h
+noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h passverify.h
 
-sbin_PROGRAMS = unix_chkpwd
+sbin_PROGRAMS = unix_chkpwd unix_update
 
 noinst_PROGRAMS = bigcrypt
 
@@ -48,11 +49,16 @@
 bigcrypt_CFLAGS = $(AM_CFLAGS)
 bigcrypt_LDFLAGS = @LIBCRYPT@
 
-unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c
+unix_chkpwd_SOURCES = unix_chkpwd.c passverify.c md5_good.c md5_broken.c bigcrypt.c
 unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
 unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ -L$(top_builddir)/libpam -lpam \
 	@LIBCRYPT@ @LIBSELINUX@
 
+unix_update_SOURCES = unix_update.c passverify.c md5_good.c md5_broken.c bigcrypt.c
+unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
+unix_update_LDFLAGS = @PIE_LDFLAGS@ -L$(top_builddir)/libpam -lpam \
+	@LIBCRYPT@ @LIBSELINUX@
+
 if ENABLE_REGENERATE_MAN
 noinst_DATA = README
 README: pam_unix.8.xml

pam-0.99.7.1-unix-bigcrypt.patch:

Index: pam-0.99.7.1-unix-bigcrypt.patch
===================================================================
RCS file: /cvs/extras/rpms/pam/devel/pam-0.99.7.1-unix-bigcrypt.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- pam-0.99.7.1-unix-bigcrypt.patch	21 Feb 2007 20:32:28 -0000	1.1
+++ pam-0.99.7.1-unix-bigcrypt.patch	4 Jun 2007 14:22:15 -0000	1.2
@@ -1,15 +1,15 @@
---- Linux-PAM-0.99.7.1/modules/pam_unix/support.c.bigcrypt	2007-02-21 20:30:24.000000000 +0100
-+++ Linux-PAM-0.99.7.1/modules/pam_unix/support.c	2007-02-21 21:17:29.000000000 +0100
-@@ -694,7 +694,7 @@
+--- Linux-PAM-0.99.7.1/modules/pam_unix/support.c.bigcrypt	2007-01-23 10:41:21.000000000 +0100
++++ Linux-PAM-0.99.7.1/modules/pam_unix/support.c	2007-06-01 15:11:51.000000000 +0200
+@@ -679,7 +679,7 @@
  			}
  		}
  	} else {
--	    int salt_len;
-+	    size_t salt_len;
- 	    strip_hpux_aging(salt);
- 	    salt_len = strlen(salt);
+-	    int salt_len = strlen(salt);
++	    size_t salt_len = strlen(salt);
  	    if (!salt_len) {
-@@ -706,19 +706,19 @@
+ 		/* the stored password is NULL */
+ 		if (off(UNIX__NONULL, ctrl)) {/* this means we've succeeded */
+@@ -689,19 +689,19 @@
  		    D(("user has empty password - access denied"));
  		    retval = PAM_AUTH_ERR;
  		}
@@ -33,7 +33,7 @@
  		    }
  		} else {
                      /*
-@@ -732,7 +732,7 @@
+@@ -715,7 +715,7 @@
  		/* the moment of truth -- do we agree with the password? */
  		D(("comparing state of pp[%s] and salt[%s]", pp, salt));
  
@@ -42,9 +42,9 @@
  		    retval = PAM_SUCCESS;
  		} else {
  		    retval = PAM_AUTH_ERR;
---- Linux-PAM-0.99.7.1/modules/pam_unix/unix_chkpwd.c.bigcrypt	2007-02-21 20:30:24.000000000 +0100
-+++ Linux-PAM-0.99.7.1/modules/pam_unix/unix_chkpwd.c	2007-02-21 21:18:57.000000000 +0100
-@@ -159,7 +159,7 @@
+--- Linux-PAM-0.99.7.1/modules/pam_unix/unix_chkpwd.c.bigcrypt	2006-10-24 12:01:49.000000000 +0200
++++ Linux-PAM-0.99.7.1/modules/pam_unix/unix_chkpwd.c	2007-06-01 15:08:46.000000000 +0200
+@@ -144,7 +144,7 @@
  	char *salt = NULL;
  	char *pp = NULL;
  	int retval = PAM_AUTH_ERR;
@@ -53,7 +53,7 @@
  
  	/* UNIX passwords area */
  	setpwent();
-@@ -205,6 +205,8 @@
+@@ -189,6 +189,8 @@
  		return (nullok == 0) ? PAM_AUTH_ERR : PAM_SUCCESS;
  	}
  	if (p == NULL || strlen(p) == 0) {
@@ -62,7 +62,7 @@
  		return PAM_AUTHTOK_ERR;
  	}
  
-@@ -212,11 +214,13 @@
+@@ -196,11 +198,13 @@
  	retval = PAM_AUTH_ERR;
  	if (!strncmp(salt, "$1$", 3)) {
  		pp = Goodcrypt_md5(p, salt);
@@ -78,7 +78,7 @@
  				retval = PAM_SUCCESS;
  		}
  	} else if (*salt == '$') {
-@@ -225,10 +229,10 @@
+@@ -209,10 +213,10 @@
  		 * libcrypt nows about it? We should try it.
  		 */
  	        pp = x_strdup (crypt(p, salt));
@@ -91,7 +91,7 @@
  	    retval = PAM_AUTH_ERR;
  	} else {
  		pp = bigcrypt(p, salt);
-@@ -239,24 +243,21 @@
+@@ -223,24 +227,21 @@
  		 * have been truncated for storage relative to the output
  		 * of bigcrypt here. As such we need to compare only the
  		 * stored string with the subset of bigcrypt's result.


Index: pam.spec
===================================================================
RCS file: /cvs/extras/rpms/pam/devel/pam.spec,v
retrieving revision 1.146
retrieving revision 1.147
diff -u -r1.146 -r1.147
--- pam.spec	13 Apr 2007 16:14:38 -0000	1.146
+++ pam.spec	4 Jun 2007 14:22:15 -0000	1.147
@@ -11,7 +11,7 @@
 Summary: A security tool which provides authentication for applications
 Name: pam
 Version: 0.99.7.1
-Release: 5%{?dist}
+Release: 6%{?dist}
 License: GPL or BSD
 Group: System Environment/Base
 Source0: http://ftp.us.kernel.org/pub/linux/libs/pam/pre/library/Linux-PAM-%{version}.tar.bz2
@@ -27,9 +27,10 @@
 Patch1:  pam-0.99.7.0-redhat-modules.patch
 Patch2:  pam-0.99.7.1-console-more-displays.patch
 Patch3:  pam-0.99.7.1-console-decrement.patch
-Patch21: pam-0.78-unix-hpux-aging.patch
 Patch22: pam-0.99.7.1-unix-allow-pwmodify.patch
 Patch23: pam-0.99.7.1-unix-bigcrypt.patch
+Patch24: pam-0.99.7.1-unix-update-helper.patch
+Patch25: pam-0.99.7.1-unix-hpux-aging.patch
 Patch34: pam-0.99.7.0-dbpam.patch
 Patch70: pam-0.99.2.1-selinux-nofail.patch
 Patch80: pam-0.99.6.2-selinux-drop-multiple.patch
@@ -45,6 +46,8 @@
 Patch96: pam-0.99.6.2-namespace-dirnames.patch
 Patch97: pam-0.99.7.1-namespace-unknown-user.patch
 Patch98: pam-0.99.6.2-selinux-audit-context.patch
+Patch99: pam-0.99.6.2-namespace-docfix.patch
+Patch100: pam-0.99.7.1-namespace-temp-logon.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires: cracklib, cracklib-dicts >= 2.8
@@ -100,9 +103,10 @@
 %patch1 -p1 -b .redhat-modules
 %patch2 -p1 -b .displays
 %patch3 -p1 -b .decrement
-%patch21 -p1 -b .unix-hpux-aging
 %patch22 -p1 -b .pwmodify
 %patch23 -p1 -b .bigcrypt
+%patch24 -p1 -b .update-helper
+%patch25 -p1 -b .unix-hpux-aging
 %patch34 -p1 -b .dbpam
 %patch70 -p1 -b .nofail
 %patch80 -p1 -b .drop-multiple
@@ -118,6 +122,8 @@
 %patch96 -p1 -b .dirnames
 %patch97 -p1 -b .unknown-user
 %patch98 -p1 -b .audit-context
+%patch99 -p1 -b .docfix
+%patch100 -p1 -b .temp-logon
 
 autoreconf
 
@@ -319,6 +325,7 @@
 %{_sbindir}/pam_tally2
 %attr(4755,root,root) %{_sbindir}/pam_timestamp_check
 %attr(4755,root,root) %{_sbindir}/unix_chkpwd
+%attr(0700,root,root) %{_sbindir}/unix_update
 %if %{_lib} != lib
 %dir /lib/security
 %endif
@@ -406,6 +413,11 @@
 %doc doc/adg/*.txt doc/adg/html
 
 %changelog
+* Thu Apr 26 2007 Tomas Mraz <tmraz at redhat.com> 0.99.7.1-6
+- pam_namespace: better document behavior on failure (#237249)
+- pam_unix: split out passwd change to a new helper binary (#236316)
+- pam_namespace: add support for temporary logons (#241226)
+
 * Fri Apr 13 2007 Tomas Mraz <tmraz at redhat.com> 0.99.7.1-5
 - pam_selinux: improve context change auditing (#234781)
 - pam_namespace: fix parsing config file with unknown users (#234513)


--- pam-0.78-unix-hpux-aging.patch DELETED ---




More information about the fedora-extras-commits mailing list