rpms/pam/F-8 pam-0.99.8.1-audit-failed.patch, NONE, 1.1 pam-0.99.8.1-sepermit-kill-user.patch, NONE, 1.1 pam-0.99.8.1-setkeycreatecon.patch, NONE, 1.1 pam-0.99.8.1-substack.patch, NONE, 1.1 pam-0.99.8.1-tty-audit.patch, NONE, 1.1 pam-0.99.8.1-tty-audit2.patch, NONE, 1.1 pam-0.99.8.1-unix-hpux-aging.patch, NONE, 1.1 pam-0.99.8.1-unix-update-helper.patch, 1.2, 1.3 pam.spec, 1.161, 1.162 pam-0.99.7.1-unix-hpux-aging.patch, 1.1, NONE pam-0.99.8.1-unix-blankpass.patch, 1.2, NONE

Tomas Mraz (tmraz) fedora-extras-commits at redhat.com
Thu Jan 31 16:15:14 UTC 2008


Author: tmraz

Update of /cvs/pkgs/rpms/pam/F-8
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv10645

Modified Files:
	pam-0.99.8.1-unix-update-helper.patch pam.spec 
Added Files:
	pam-0.99.8.1-audit-failed.patch 
	pam-0.99.8.1-sepermit-kill-user.patch 
	pam-0.99.8.1-setkeycreatecon.patch pam-0.99.8.1-substack.patch 
	pam-0.99.8.1-tty-audit.patch pam-0.99.8.1-tty-audit2.patch 
	pam-0.99.8.1-unix-hpux-aging.patch 
Removed Files:
	pam-0.99.7.1-unix-hpux-aging.patch 
	pam-0.99.8.1-unix-blankpass.patch 
Log Message:
- sync with rawhide

pam-0.99.8.1-audit-failed.patch:

--- NEW FILE pam-0.99.8.1-audit-failed.patch ---
diff -up Linux-PAM-0.99.8.1/libpam/libpam.map.audit-failed Linux-PAM-0.99.8.1/libpam/libpam.map
--- Linux-PAM-0.99.8.1/libpam/libpam.map.audit-failed	2006-06-14 17:28:44.000000000 +0200
+++ Linux-PAM-0.99.8.1/libpam/libpam.map	2008-01-22 22:24:05.000000000 +0100
@@ -45,3 +45,7 @@ LIBPAM_MODUTIL_1.0 {
     pam_modutil_read;
     pam_modutil_write;
 };
+LIBPAM_MODUTIL_1.1 {
+  global:
+    pam_modutil_audit_write;
+} LIBPAM_MODUTIL_1.0;
diff -up Linux-PAM-0.99.8.1/libpam/pam_audit.c.audit-failed Linux-PAM-0.99.8.1/libpam/pam_audit.c
--- Linux-PAM-0.99.8.1/libpam/pam_audit.c.audit-failed	2008-01-22 22:24:05.000000000 +0100
+++ Linux-PAM-0.99.8.1/libpam/pam_audit.c	2008-01-22 22:24:05.000000000 +0100
@@ -42,39 +42,53 @@ _pam_audit_writelog(pam_handle_t *pamh, 
      best to fix it. */
   errno = -rc;
 
+  if (rc < 0 && errno != old_errno)
+    {
+      old_errno = errno;
+      pam_syslog (pamh, LOG_CRIT, "audit_log_acct_message() failed: %m");
+    }
+
   pamh->audit_state |= PAMAUDIT_LOGGED;
 
-  if (rc < 0) {
-      if (rc == -EPERM && getuid() != 0)
-          return 0;
-      if (errno != old_errno) {
-          old_errno = errno;
-          pam_syslog (pamh, LOG_CRIT, "audit_log_acct_message() failed: %m");
-      }
-  }
-  return rc;
+  if (rc == -EPERM && getuid () != 0)
+    return 0;
+  else
+    return rc;
 }
 
-int
-_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
+static int
+_pam_audit_open(pam_handle_t *pamh)
 {
-  const char *message;
-  int type;
   int audit_fd;
-
   audit_fd = audit_open();
   if (audit_fd < 0) {
     /* You get these error codes only when the kernel doesn't have
      * audit compiled in. */
     if (errno == EINVAL || errno == EPROTONOSUPPORT ||
         errno == EAFNOSUPPORT)
-        return retval;
+        return -2;
 
     /* this should only fail in case of extreme resource shortage,
      * need to prevent login in that case for CAPP compliance.
      */
     pam_syslog(pamh, LOG_CRIT, "audit_open() failed: %m");
+    return -1;
+  }
+
+  return audit_fd;
+}
+
+int
+_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
+{
+  const char *message;
+  int type;
+  int audit_fd;
+
+  if ((audit_fd=_pam_audit_open(pamh)) == -1) {
     return PAM_SYSTEM_ERR;
+  } else if (audit_fd == -2) {
+    return retval;
   }
 
   switch (action) {
@@ -141,4 +155,30 @@ _pam_audit_end(pam_handle_t *pamh, int s
   return 0;
 }
 
+int
+pam_modutil_audit_write(pam_handle_t *pamh, int type,
+    const char *message, int retval)
+{
+  int audit_fd;
+  int rc;
+	
+  if ((audit_fd=_pam_audit_open(pamh)) == -1) {
+    return PAM_SYSTEM_ERR;
+  } else if (audit_fd == -2) {
+    return retval;
+  }
+
+  rc = _pam_audit_writelog(pamh, audit_fd, type, message, retval);
+
+  audit_close(audit_fd);
+  
+  return rc < 0 ? PAM_SYSTEM_ERR : PAM_SUCCESS;
+}
+
+#else
+int pam_modutil_audit_write(pam_handle_t *pamh UNUSED, int type UNUSED,
+    const char *message UNUSED, int retval UNUSED)
+{
+  return PAM_SUCCESS;
+}
 #endif /* HAVE_LIBAUDIT */
diff -up Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml
--- Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml.audit-failed	2007-06-22 10:03:29.000000000 +0200
+++ Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml	2008-01-22 22:24:05.000000000 +0100
@@ -29,6 +29,9 @@
         nodefgroup
       </arg>
       <arg choice="opt">
+        noaudit
+      </arg>
+      <arg choice="opt">
         accessfile=<replaceable>file</replaceable>
       </arg>
       <arg choice="opt">
@@ -54,6 +57,10 @@
       <filename>/etc/security/access.conf</filename> if you don't specify
       another file.
     </para>
+    <para>
+      If Linux PAM is compiled with audit support the module will report
+      when it denies access based on origin (host or tty). 
+    </para>
   </refsect1>
 
   <refsect1 id="pam_access-options">
@@ -87,6 +94,17 @@
 
       <varlistentry>
         <term>
+          <option>noaudit</option>
+        </term>
+        <listitem>
+          <para>
+            Do not report logins from disallowed hosts and ttys to the audit subsystem.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
           <option>fieldsep=<replaceable>separators</replaceable></option>
         </term>
         <listitem>
diff -up Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c
--- Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c.audit-failed	2007-06-25 11:59:11.000000000 +0200
+++ Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c	2008-01-22 22:24:05.000000000 +0100
@@ -46,6 +46,10 @@
 #include <netdb.h>
 #include <sys/socket.h>
 
+#ifdef HAVE_LIBAUDIT
+#include <libaudit.h>
+#endif                                                                                                                                         
+
 /*
  * here, we make definitions for the externally accessible functions
  * in this file (these definitions are required for static modules
@@ -81,17 +85,11 @@
 
  /* Delimiters for fields and for lists of users, ttys or hosts. */
 
-static const char *fs = ":";			/* field separator */
-static const char *sep = ", \t";		/* list-element separator */
-
- /* Constants to be used in assignments only, not in comparisons... */
 
+#define ALL             2
 #define YES             1
 #define NO              0
 
-/* Only allow group entries of the form "(xyz)" */
-static int only_new_group_syntax = NO;
-
  /*
   * A structure to bundle up all login-related information to keep the
   * functional interfaces as generic as possible.
@@ -100,12 +98,13 @@ struct login_info {
     const struct passwd *user;
     const char *from;
     const char *config_file;
+    int debug;              		/* Print debugging messages. */
+    int only_new_group_syntax;		/* Only allow group entries of the form "(xyz)" */
+    int noaudit;			/* Do not audit denials */
+    const char *fs;			/* field separator */
+    const char *sep;			/* list-element separator */
 };
 
-/* Print debugging messages.
-   Default is NO which means don't print debugging messages.  */
-static char pam_access_debug = NO;
-
 /* Parse module config arguments */
 
 static int
@@ -113,17 +112,22 @@ parse_args(pam_handle_t *pamh, struct lo
            int argc, const char **argv)
 {
     int i;
-
+    
+    loginfo->noaudit = NO;
+    loginfo->debug = NO;
+    loginfo->only_new_group_syntax = NO;
+    loginfo->fs = ":";
+    loginfo->sep = ", \t";
     for (i=0; i<argc; ++i) {
 	if (!strncmp("fieldsep=", argv[i], 9)) {
 
 	    /* the admin wants to override the default field separators */
-	    fs = argv[i]+9;
+	    loginfo->fs = argv[i]+9;
 
 	} else if (!strncmp("listsep=", argv[i], 8)) {
 
 	    /* the admin wants to override the default list separators */
-	    sep = argv[i]+8;
+	    loginfo->sep = argv[i]+8;
 
 	} else if (!strncmp("accessfile=", argv[i], 11)) {
 	    FILE *fp = fopen(11 + argv[i], "r");
@@ -138,9 +142,11 @@ parse_args(pam_handle_t *pamh, struct lo
 	    }
 
 	} else if (strcmp (argv[i], "debug") == 0) {
-	    pam_access_debug = YES;
+	    loginfo->debug = YES;
 	} else if (strcmp (argv[i], "nodefgroup") == 0) {
-	    only_new_group_syntax = YES;
+	    loginfo->only_new_group_syntax = YES;
+	} else if (strcmp (argv[i], "noaudit") == 0) {
+	    loginfo->noaudit = YES;
 	} else {
 	    pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", argv[i]);
 	}
@@ -153,13 +159,13 @@ parse_args(pam_handle_t *pamh, struct lo
 
 typedef int match_func (pam_handle_t *, char *, struct login_info *);
 
-static int list_match (pam_handle_t *, char *, struct login_info *,
+static int list_match (pam_handle_t *, char *, char *, struct login_info *,
 		       match_func *);
 static int user_match (pam_handle_t *, char *, struct login_info *);
-static int group_match (pam_handle_t *, const char *, const char *);
+static int group_match (pam_handle_t *, const char *, const char *, int);
 static int from_match (pam_handle_t *, char *, struct login_info *);
-static int string_match (pam_handle_t *, const char *, const char *);
-static int network_netmask_match (pam_handle_t *, const char *, const char *);
+static int string_match (pam_handle_t *, const char *, const char *, int);
+static int network_netmask_match (pam_handle_t *, const char *, const char *, int);
 
 
 /* isipaddr - find out if string provided is an IP address or not */
@@ -325,11 +331,12 @@ login_access (pam_handle_t *pamh, struct
     char   *users;		/* becomes list of login names */
     char   *froms;		/* becomes list of terminals or hosts */
     int     match = NO;
+    int     nonall_match = NO;
     int     end;
     int     lineno = 0;		/* for diagnostics */
     char   *sptr;
 
-    if (pam_access_debug)
+    if (item->debug)
       pam_syslog (pamh, LOG_DEBUG,
 		  "login_access: user=%s, from=%s, file=%s",
 		  item->user->pw_name,
@@ -361,8 +368,8 @@ login_access (pam_handle_t *pamh, struct
 		continue;
 
 	    /* Allow field seperator in last field of froms */
-	    if (!(perm = strtok_r(line, fs, &sptr))
-		|| !(users = strtok_r(NULL, fs, &sptr))
+	    if (!(perm = strtok_r(line, item->fs, &sptr))
+		|| !(users = strtok_r(NULL, item->fs, &sptr))
   	        || !(froms = strtok_r(NULL, "\n", &sptr))) {
 		pam_syslog(pamh, LOG_ERR, "%s: line %d: bad field count",
 			   item->config_file, lineno);
@@ -373,17 +380,22 @@ login_access (pam_handle_t *pamh, struct
 			   item->config_file, lineno);
 		continue;
 	    }
-	    if (pam_access_debug)
+	    if (item->debug)
 	      pam_syslog (pamh, LOG_DEBUG,
 			  "line %d: %s : %s : %s", lineno, perm, users, froms);
-	    match = list_match(pamh, froms, item, from_match);
-	    if (pam_access_debug)
-	      pam_syslog (pamh, LOG_DEBUG,
-			  "from_match=%d, \"%s\"", match, item->from);
-	    match = match && list_match (pamh, users, item, user_match);
-	    if (pam_access_debug)
+	    match = list_match(pamh, users, NULL, item, user_match);
+	    if (item->debug)
 	      pam_syslog (pamh, LOG_DEBUG, "user_match=%d, \"%s\"",
 			  match, item->user->pw_name);
+	    if (match) {
+		match = list_match(pamh, froms, NULL, item, from_match);
+		if (!match && perm[0] == '+') {
+		    nonall_match = YES;
+		}
+		if (item->debug)
+	    	    pam_syslog (pamh, LOG_DEBUG,
+			  "from_match=%d, \"%s\"", match, item->from);
+	    }
 	}
 	(void) fclose(fp);
     } else if (errno == ENOENT) {
@@ -394,20 +406,27 @@ login_access (pam_handle_t *pamh, struct
         pam_syslog(pamh, LOG_ERR, "cannot open %s: %m", item->config_file);
 	return NO;
     }
+#ifdef HAVE_LIBAUDIT
+    if (!item->noaudit && line[0] == '-' && (match == YES || (match == ALL &&
+	nonall_match == YES))) {
+	pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_LOCATION,
+	    "pam_access", 0);
+    }
+#endif
     return (match == NO || (line[0] == '+'));
 }
 
 
 /* list_match - match an item against a list of tokens with exceptions */
 
-static int list_match(pam_handle_t *pamh,
-		      char *list, struct login_info *item, match_func *match_fn)
+static int
+list_match(pam_handle_t *pamh, char *list, char *sptr,
+	   struct login_info *item, match_func *match_fn)
 {
     char   *tok;
     int     match = NO;
-    char   *sptr;
 
-    if (pam_access_debug)
+    if (item->debug && list != NULL)
       pam_syslog (pamh, LOG_DEBUG,
 		  "list_match: list=%s, item=%s", list, item->user->pw_name);
 
@@ -418,8 +437,8 @@ static int list_match(pam_handle_t *pamh
      * the match is affected by any exceptions.
      */
 
-    for (tok = strtok_r(list, sep, &sptr); tok != 0;
-	 tok = strtok_r(NULL, sep, &sptr)) {
+    for (tok = strtok_r(list, item->sep, &sptr); tok != 0;
+	 tok = strtok_r(NULL, item->sep, &sptr)) {
 	if (strcasecmp(tok, "EXCEPT") == 0)	/* EXCEPT: give up */
 	    break;
 	if ((match = (*match_fn) (pamh, tok, item)))	/* YES */
@@ -428,10 +447,12 @@ static int list_match(pam_handle_t *pamh
     /* Process exceptions to matches. */
 
     if (match != NO) {
-	while ((tok = strtok_r(NULL, sep, &sptr)) && strcasecmp(tok, "EXCEPT"))
+	while ((tok = strtok_r(NULL, item->sep, &sptr)) && strcasecmp(tok, "EXCEPT"))
 	     /* VOID */ ;
-	if (tok == 0 || list_match(pamh, sptr, item, match_fn) == NO)
-	    return (match);
+	if (tok == 0)
+	    return match;
+	if (list_match(pamh, NULL, sptr, item, match_fn) == NO)
+	    return YES; /* drop special meaning of ALL */
     }
     return (NO);
 }
@@ -453,7 +474,7 @@ static char *myhostname(void)
 
 static int
 netgroup_match (pam_handle_t *pamh, const char *netgroup,
-		const char *machine, const char *user)
+		const char *machine, const char *user, int debug)
 {
   char *mydomain = NULL;
   int retval;
@@ -462,7 +483,7 @@ netgroup_match (pam_handle_t *pamh, cons
 
 
   retval = innetgr (netgroup, machine, user, mydomain);
-  if (pam_access_debug == YES)
+  if (debug == YES)
     pam_syslog (pamh, LOG_DEBUG,
 		"netgroup_match: %d (netgroup=%s, machine=%s, user=%s, domain=%s)",
 		retval, netgroup ? netgroup : "NULL",
@@ -480,8 +501,9 @@ user_match (pam_handle_t *pamh, char *to
     char   *string = item->user->pw_name;
     struct login_info fake_item;
     char   *at;
+    int    rv;
 
-    if (pam_access_debug)
+    if (item->debug)
       pam_syslog (pamh, LOG_DEBUG,
 		  "user_match: tok=%s, item=%s", tok, string);
 
@@ -500,12 +522,12 @@ user_match (pam_handle_t *pamh, char *to
 	return (user_match (pamh, tok, item) &&
 		from_match (pamh, at + 1, &fake_item));
     } else if (tok[0] == '@') /* netgroup */
-      return (netgroup_match (pamh, tok + 1, (char *) 0, string));
+      return (netgroup_match (pamh, tok + 1, (char *) 0, string, item->debug));
     else if (tok[0] == '(' && tok[strlen(tok) - 1] == ')')
-      return (group_match (pamh, tok, string));
-    else if (string_match (pamh, tok, string)) /* ALL or exact match */
-      return YES;
-    else if (only_new_group_syntax == NO &&
+      return (group_match (pamh, tok, string, item->debug));
+    else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */
+      return rv;
+    else if (item->only_new_group_syntax == NO &&
 	     pam_modutil_user_in_group_nam_nam (pamh,
 						item->user->pw_name, tok))
       /* try group membership */
@@ -518,11 +540,12 @@ user_match (pam_handle_t *pamh, char *to
 /* group_match - match a username against token named group */
 
 static int
-group_match (pam_handle_t *pamh, const char *tok, const char* usr)
+group_match (pam_handle_t *pamh, const char *tok, const char* usr,
+    int debug)
 {
     char grptok[BUFSIZ];
 
-    if (pam_access_debug)
+    if (debug)
         pam_syslog (pamh, LOG_DEBUG,
 		    "group_match: grp=%s, user=%s", grptok, usr);
 
@@ -548,8 +571,9 @@ from_match (pam_handle_t *pamh UNUSED, c
     const char *string = item->from;
     int        tok_len;
     int        str_len;
+    int        rv;
 
-    if (pam_access_debug)
+    if (item->debug)
       pam_syslog (pamh, LOG_DEBUG,
 		  "from_match: tok=%s, item=%s", tok, string);
 
@@ -565,10 +589,10 @@ from_match (pam_handle_t *pamh UNUSED, c
     if (string == NULL) {
 	return NO;
     } else if (tok[0] == '@') {			/* netgroup */
-        return (netgroup_match (pamh, tok + 1, string, (char *) 0));
-    } else if (string_match(pamh, tok, string)) {
+        return (netgroup_match (pamh, tok + 1, string, (char *) 0, item->debug));
+    } else if ((rv = string_match(pamh, tok, string, item->debug)) != NO) {
         /* ALL or exact match */
-	return (YES);
+	return rv;
     } else if (tok[0] == '.') {			/* domain: match last fields */
 	if ((str_len = strlen(string)) > (tok_len = strlen(tok))
 	    && strcasecmp(tok, string + str_len - tok_len) == 0)
@@ -614,7 +638,7 @@ from_match (pam_handle_t *pamh UNUSED, c
 	}
     } else  if (isipaddr(string, NULL, NULL) == YES) {
       /* Assume network/netmask with a IP of a host.  */
-      if (network_netmask_match(pamh, tok, string))
+      if (network_netmask_match(pamh, tok, string, item->debug))
 	return YES;
     } else {
       /* Assume network/netmask with a name of a host.  */
@@ -641,7 +665,7 @@ from_match (pam_handle_t *pamh UNUSED, c
 			 : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
 			 buf, sizeof (buf));
 
-	      if (network_netmask_match(pamh, tok, buf))
+	      if (network_netmask_match(pamh, tok, buf, item->debug))
 		{
 		  freeaddrinfo (res);
 		  return YES;
@@ -658,10 +682,11 @@ from_match (pam_handle_t *pamh UNUSED, c
 /* string_match - match a string against one token */
 
 static int
-string_match (pam_handle_t *pamh, const char *tok, const char *string)
+string_match (pam_handle_t *pamh, const char *tok, const char *string,
+    int debug)
 {
 
-    if (pam_access_debug)
+    if (debug)
         pam_syslog (pamh, LOG_DEBUG,
 		    "string_match: tok=%s, item=%s", tok, string);
 
@@ -672,7 +697,7 @@ string_match (pam_handle_t *pamh, const 
      */
 
     if (strcasecmp(tok, "ALL") == 0) {		/* all: always matches */
-	return (YES);
+	return (ALL);
     } else if (string != NULL) {
 	if (strcasecmp(tok, string) == 0) {	/* try exact match */
 	    return (YES);
@@ -690,9 +715,9 @@ string_match (pam_handle_t *pamh, const 
  */
 static int
 network_netmask_match (pam_handle_t *pamh,
-		       const char *tok, const char *string)
+		       const char *tok, const char *string, int debug)
 {
-  if (pam_access_debug)
+  if (debug)
     pam_syslog (pamh, LOG_DEBUG,
 		"network_netmask_match: tok=%s, item=%s", tok, string);
 
@@ -771,6 +796,22 @@ pam_sm_authenticate (pam_handle_t *pamh,
 	return PAM_USER_UNKNOWN;
     }
 
+    if ((user_pw=pam_modutil_getpwnam(pamh, user))==NULL)
+      return (PAM_USER_UNKNOWN);
+
+    /*
+     * Bundle up the arguments to avoid unnecessary clumsiness later on.
+     */
+    loginfo.user = user_pw;
+    loginfo.config_file = PAM_ACCESS_CONFIG;
+
+    /* parse the argument list */
+
+    if (!parse_args(pamh, &loginfo, argc, argv)) {
+	pam_syslog(pamh, LOG_ERR, "failed to parse the module arguments");
+	return PAM_ABORT;
+    }
+
     /* remote host name */
 
     if (pam_get_item(pamh, PAM_RHOST, &void_from)
@@ -799,7 +840,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
 		return PAM_ABORT;
 	      }
 	      from = void_from;
-	      if (pam_access_debug)
+	      if (loginfo.debug)
 		pam_syslog (pamh, LOG_DEBUG,
 			    "cannot determine tty or remote hostname, using service %s",
 			    from);
@@ -817,22 +858,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
 	}
     }
 
-    if ((user_pw=pam_modutil_getpwnam(pamh, user))==NULL)
-      return (PAM_USER_UNKNOWN);
-
-    /*
-     * Bundle up the arguments to avoid unnecessary clumsiness later on.
-     */
-    loginfo.user = user_pw;
     loginfo.from = from;
-    loginfo.config_file = PAM_ACCESS_CONFIG;
-
-    /* parse the argument list */
-
-    if (!parse_args(pamh, &loginfo, argc, argv)) {
-	pam_syslog(pamh, LOG_ERR, "failed to parse the module arguments");
-	return PAM_ABORT;
-    }
 
     if (login_access(pamh, &loginfo)) {
 	return (PAM_SUCCESS);
diff -up Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c
--- Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c.audit-failed	2006-06-16 08:35:16.000000000 +0200
+++ Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c	2008-01-22 22:24:05.000000000 +0100
@@ -22,9 +22,16 @@
 #include <fcntl.h>
 #include <netdb.h>
 
+#ifdef HAVE_LIBAUDIT
+#include <libaudit.h>                                                                                                                                            
+#endif
+
 #define PAM_TIME_BUFLEN        1000
 #define FIELD_SEPARATOR        ';'   /* this is new as of .02 */
 
+#define PAM_DEBUG_ARG       0x0001
+#define PAM_NO_AUDIT        0x0002
+
 #ifndef TRUE
 # define TRUE 1
 #endif
@@ -46,6 +53,29 @@ typedef enum { AND, OR } operator;
 #include <security/_pam_macros.h>
 #include <security/pam_modules.h>
 #include <security/pam_ext.h>
+#include <security/pam_modutil.h>
+
+static int
+_pam_parse (const pam_handle_t *pamh, int argc, const char **argv)
+{
+    int ctrl = 0;
+
+    /* step through arguments */
+    for (; argc-- > 0; ++argv) {
+
+	/* generic options */
+
+	if (!strcmp(*argv, "debug")) {
+	    ctrl |= PAM_DEBUG_ARG;
+	} else if (!strcmp(*argv, "noaudit")) {
+	    ctrl |= PAM_NO_AUDIT;
+	} else {
+	    pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
+	}
+    }
+
+    return ctrl;
+}
 
 /* --- static functions for checking whether the user should be let in --- */
 
@@ -59,7 +89,7 @@ shift_bytes(char *mem, int from, int by)
 }
 
 static int
-read_field(pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
 {
     /* is buf set ? */
 
@@ -137,6 +167,7 @@ read_field(pam_handle_t *pamh, int fd, c
 	    switch ((*buf)[i]) {
 		int j,c;
 	    case '#':
+                c = 0;
 		for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
 		if (j >= *to) {
 		    (*buf)[*to = ++i] = '\0';
@@ -324,6 +355,13 @@ is_same(pam_handle_t *pamh UNUSED, const
 		    return FALSE;
 	  }
      }
+
+     /* Ok, we know that b is a substring from A and does not contain
+        wildcards, but now the length of both strings must be the same,
+        too. */
+     if (strlen (a) != strlen(b))
+          return FALSE;
+
      return ( !len );
 }
 
@@ -559,11 +597,15 @@ check_account(pam_handle_t *pamh, const 
 
 PAM_EXTERN int
 pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
-		 int argc UNUSED, const char **argv UNUSED)
+		 int argc, const char **argv)
 {
     const void *service=NULL, *void_tty=NULL;
     const char *tty;
     const char *user=NULL;
+    int ctrl;
+    int rv;
+
+    ctrl = _pam_parse(pamh, argc, argv);
 
     /* set service name */
 
@@ -612,7 +654,19 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int
     D(("user=%s", user));
     D(("tty=%s", tty));
 
-    return check_account(pamh, service, tty, user);
+    rv = check_account(pamh, service, tty, user);
+    if (rv != PAM_SUCCESS) {
+#ifdef HAVE_LIBAUDIT
+	if (!(ctrl & PAM_NO_AUDIT)) {
+            pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_TIME,
+            	    "pam_time", rv); /* ignore return value as we fail anyway */
+        }
+#endif
+	if (ctrl & PAM_DEBUG_ARG) {
+	    pam_syslog(pamh, LOG_DEBUG, "user %s rejected", user);
+	}
+    }
+    return rv;
 }
 
 /* end of module definition */
diff -up Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml
--- Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml.audit-failed	2006-06-22 21:44:30.000000000 +0200
+++ Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml	2008-01-22 22:24:05.000000000 +0100
@@ -22,6 +22,12 @@
   <refsynopsisdiv>
     <cmdsynopsis id="pam_time-cmdsynopsis">
       <command>pam_time.so</command>
+      <arg choice="opt">
+        debug
+      </arg>
+      <arg choice="opt">
+        noaudit
+      </arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -41,11 +47,40 @@
       By default rules for time/port access are taken from config file
       <filename>/etc/security/time.conf</filename>.
     </para>
+    <para>
+      If Linux PAM is compiled with audit support the module will report
+      when it denies access. 
+    </para>
   </refsect1>
 
   <refsect1 id="pam_time-options">
     <title>OPTIONS</title>
-    <para>This module does not recognice any options.</para>
+    <variablelist>
+
+      <varlistentry>
+        <term>
+          <option>debug</option>
+        </term>
+        <listitem>
+          <para>
+            Some debug informations are printed with
+            <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
+          <option>noaudit</option>
+        </term>
+        <listitem>
+          <para>
+            Do not report logins at disallowed time to the audit subsystem.
+          </para>
+        </listitem>
+      </varlistentry>
+
+    </variablelist>
   </refsect1>
 
   <refsect1 id="pam_time-services">
diff -up Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c
--- Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c.audit-failed	2007-07-10 12:10:56.000000000 +0200
+++ Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c	2008-01-22 22:41:40.000000000 +0100
@@ -41,6 +41,10 @@
 #include <pwd.h>
 #include <locale.h>
 
+#ifdef HAVE_LIBAUDIT
+#include <libaudit.h>                                                                                                                                            
+#endif
+
 /* Module defines */
 #define LINE_LENGTH 1024
 
@@ -101,6 +105,7 @@ struct pam_limit_s {
 #define PAM_DEBUG_ARG       0x0001
 #define PAM_DO_SETREUID     0x0002
 #define PAM_UTMP_EARLY      0x0004
+#define PAM_NO_AUDIT        0x0008
 
 /* Limits from globbed files. */
 #define LIMITS_CONF_GLOB LIMITS_FILE_DIR
@@ -126,6 +131,8 @@ _pam_parse (const pam_handle_t *pamh, in
 	    ctrl |= PAM_DO_SETREUID;
 	} else if (!strcmp(*argv,"utmp_early")) {
 	    ctrl |= PAM_UTMP_EARLY;
+	} else if (!strcmp(*argv,"noaudit")) {
+	    ctrl |= PAM_NO_AUDIT;
 	} else {
 	    pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
 	}
@@ -599,6 +606,13 @@ static int setup_limits(pam_handle_t *pa
 	D(("skip login limit check for uid=0"));
     } else if (pl->login_limit > 0) {
         if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
+#ifdef HAVE_LIBAUDIT
+	    if (!(ctrl & PAM_NO_AUDIT)) {
+        	pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_SESSIONS,
+            	    "pam_limits", PAM_PERM_DENIED);
+		/* ignore return value as we fail anyway */
+            }
+#endif
             retval |= LOGIN_ERR;
 	}
     } else if (pl->login_limit == 0) {
diff -up Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml
--- Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml.audit-failed	2007-04-30 12:47:26.000000000 +0200
+++ Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml	2008-01-22 22:24:05.000000000 +0100
@@ -34,6 +34,9 @@
       <arg choice="opt">
         utmp_early
       </arg>
+      <arg choice="opt">
+        noaudit
+      </arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -57,6 +60,11 @@
     <para>
       The module must not be called by a multithreaded application.
     </para>
+    <para>
+      If Linux PAM is compiled with audit support the module will report
+      when it denies access based on limit of maximum number of concurrent
+      login sessions.
+    </para>
   </refsect1>
 
   <refsect1 id="pam_limits-options">
@@ -111,6 +119,16 @@
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term>
+          <option>noaudit</option>
+        </term>
+        <listitem>
+          <para>
+            Do not report exceeded maximum logins count to the audit subsystem.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 

pam-0.99.8.1-sepermit-kill-user.patch:

--- NEW FILE pam-0.99.8.1-sepermit-kill-user.patch ---
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c
--- Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c.kill-user	2008-01-28 18:34:18.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c	2008-01-28 18:34:18.000000000 +0100
@@ -1,7 +1,7 @@
 /******************************************************************************
  * A module for Linux-PAM that allows/denies acces based on SELinux state.
  *
- * Copyright (c) 2007 Red Hat, Inc.
+ * Copyright (c) 2007, 2008 Red Hat, Inc.
  * Written by Tomas Mraz <tmraz at redhat.com>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,14 @@
 #include <string.h>
 #include <syslog.h>
 #include <ctype.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <dirent.h>
 
 #define PAM_SM_AUTH
 #define PAM_SM_ACCOUNT
@@ -57,6 +65,165 @@
 
 #include <selinux/selinux.h>
 
+#define MODULE "pam_selinux_permit"
+#define OPT_DELIM ":"
+
+struct lockfd {
+	uid_t uid;
+	int fd;
+        int debug;
+};
+
+#define PROC_BASE "/proc"
+#define MAX_NAMES (int)(sizeof(unsigned long)*8)
+
+static int
+match_process_uid(pid_t pid, uid_t uid)
+{
+	char buf[128];
+	uid_t puid;
+	FILE *f;
+	int re = 0;
+	
+	snprintf (buf, sizeof buf, PROC_BASE "/%d/status", pid);
+	if (!(f = fopen (buf, "r")))
+		return 0;
+	
+	while (fgets(buf, sizeof buf, f)) {
+		if (sscanf (buf, "Uid:\t%d", &puid)) {
+			re = uid == puid;
+			break;
+		}
+	}
+	fclose(f);
+	return re;
+}
+
+static int
+check_running (pam_handle_t *pamh, uid_t uid, int killall, int debug)
+{
+	DIR *dir;
+	struct dirent *de;
+	pid_t *pid_table, pid, self;
+	int i;
+	int pids, max_pids;
+	int running = 0;
+	self = getpid();
+	if (!(dir = opendir(PROC_BASE))) {
+		pam_syslog(pamh, LOG_ERR, "Failed to open proc directory file %s:", PROC_BASE);
+		return -1;
+	}
+	max_pids = 256;
+	pid_table = malloc(max_pids * sizeof (pid_t));
+	if (!pid_table) {
+		pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
+		return -1;
+	}
+	pids = 0;
+	while ((de = readdir (dir)) != NULL) {
+		if (!(pid = (pid_t)atoi(de->d_name)) || pid == self)
+			continue;
+
+		if (pids == max_pids) {
+			if (!(pid_table = realloc(pid_table, 2*pids*sizeof(pid_t)))) {
+				pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
+				return -1;
+			}
+			max_pids *= 2;
+		}
+		pid_table[pids++] = pid;
+	}
+
+	(void)closedir(dir);
+
+	for (i = 0; i < pids; i++) {
+		pid_t id;
+
+		if (match_process_uid(pid_table[i], uid) == 0)
+			continue;
+		id = pid_table[i];
+
+		if (killall) {
+			if (debug)
+				pam_syslog(pamh, LOG_NOTICE, "Attempting to kill %d", id);
+			kill(id, SIGKILL);
+		}
+		running++;
+	}
+
+	free(pid_table);
+	return running;
+}
+
+static void
+sepermit_unlock(pam_handle_t *pamh, void *plockfd, int error_status UNUSED)
+{
+	struct lockfd *lockfd = plockfd;
+	struct flock fl;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.l_type = F_UNLCK;
+	fl.l_whence = SEEK_SET;
+
+	if (lockfd->debug)
+		pam_syslog(pamh, LOG_ERR, "Unlocking fd: %d uid: %d", lockfd->fd, lockfd->uid);
+
+	/* Don't kill uid==0 */
+	if (lockfd->uid)
+		/* This is a DOS but it prevents an app from forking to prevent killing */
+		while(check_running(pamh, lockfd->uid, 1, lockfd->debug) > 0)
+			continue;
+
+	fcntl(lockfd->fd, F_SETLK, &fl);
+	close(lockfd->fd);
+	free(lockfd);
+}
+
+static int
+sepermit_lock(pam_handle_t *pamh, const char *user, int debug)
+{
+	char buf[PATH_MAX];
+	struct flock fl;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.l_type = F_WRLCK;
+	fl.l_whence = SEEK_SET;
+
+	struct passwd *pw = pam_modutil_getpwnam( pamh, user );
+	if (!pw) {
+		pam_syslog(pamh, LOG_ERR, "Unable to find uid for user %s", user);
+		return -1;
+	}
+	if (check_running(pamh, pw->pw_uid, 0, debug) > 0)  {
+		pam_syslog(pamh, LOG_ERR, "User %s processes are running. Exclusive login not allowed", user);
+		return -1;
+	}
+
+	snprintf(buf, sizeof(buf), "%s/%d.lock", SEPERMIT_LOCKDIR, pw->pw_uid);
+	int fd = open(buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+	if (fd < 0) {
+		pam_syslog(pamh, LOG_ERR, "Unable to open lock file %s/%d.lock", SEPERMIT_LOCKDIR, pw->pw_uid);
+		return -1;
+	}
+
+	if (fcntl(fd, F_SETLK, &fl) == -1) {
+		pam_syslog(pamh, LOG_ERR, "User %s with exclusive login already logged in", user);
+		close(fd);
+		return -1;
+	}
+	struct lockfd *lockfd=calloc(1, sizeof(struct lockfd));
+	if (!lockfd) {
+		close(fd);
+		pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
+		return -1;
+	}
+	lockfd->uid = pw->pw_uid;
+	lockfd->debug = debug;
+	lockfd->fd=fd;
+        pam_set_data(pamh, "pam_selinux_permit", lockfd, sepermit_unlock);
+	return 0;
+}
+
 /* return 0 when matched, -1 when unmatched, pam error otherwise */
 static int
 sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user,
@@ -67,6 +234,7 @@ sepermit_match(pam_handle_t *pamh, const
 	char *start;
 	size_t len = 0;
 	int matched = 0;
+	int exclusive = 0;
 	
 	f = fopen(cfgfile, "r");
 	
@@ -77,6 +245,8 @@ sepermit_match(pam_handle_t *pamh, const
 
 	while (!matched && getline(&line, &len, f) != -1) {
 		size_t n;
+		char *sptr;
+		char *opt;
 
 		if (line[0] == '#')
 			continue;
@@ -92,6 +262,7 @@ sepermit_match(pam_handle_t *pamh, const
 			continue;
 
 		start[n] = '\0';
+		start = strtok_r(start, OPT_DELIM, &sptr);
 
 		switch (start[0]) {
 			case '@': 
@@ -117,11 +288,22 @@ sepermit_match(pam_handle_t *pamh, const
 					matched = 1;
 				}
 		}
+		if (matched)
+			while ((opt=strtok_r(NULL, OPT_DELIM, &sptr)) != NULL) {
+				if (strcmp(opt, "exclusive") == 0)
+					exclusive = 1;
+				else if (debug) {
+					pam_syslog(pamh, LOG_NOTICE, "Unknown user option: %s", opt);
+				}
+			}
 	}
 
 	free(line);
 	fclose(f);
-	return matched ? 0 : -1;
+	if (matched) 
+		return exclusive ? sepermit_lock(pamh, user, debug) : 0;
+	else
+		return -1;
 }
 
 PAM_EXTERN int
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml
--- Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml.kill-user	2008-01-28 18:34:18.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml	2008-01-28 18:34:18.000000000 +0100
@@ -30,8 +30,8 @@
   <refsect1 id="pam_selinux_permit-description">
     <title>DESCRIPTION</title>
     <para>
-      The pam_selinux module allows or denies login depending on SELinux enforcement
-      state.
+      The pam_selinux_permit module allows or denies login depending on SELinux
+      enforcement state.
     </para>
     <para>
       When the user which is logging in matches an entry in the config file
@@ -41,14 +41,21 @@
     </para>
     <para>
       The config file contains a simple list of user names one per line. If the
-      <replaceable>name</replaceable> is prefixed with @ character it means that all
+      <replaceable>name</replaceable> is prefixed with <emphasis>@</emphasis> character it means that all
       users in the group <replaceable>name</replaceable> match. If it is prefixed
-      with a % character the SELinux user is used to match against the <replaceable>name</replaceable>
+      with a <emphasis>%</emphasis> character the SELinux user is used to match against the <replaceable>name</replaceable>
       instead of the account name. Note that when SELinux is disabled the
       SELinux user assigned to the account cannot be determined. This means that
       such entries are never matched when SELinux is disabled and pam_selinux_permit
       will return PAM_IGNORE.
     </para>
+    <para>
+      Each user name in the configuration file can have optional arguments separated
+      by <emphasis>:</emphasis> character. The only currently recognized argument is <emphasis>exclusive</emphasis>.
+      The pam_selinux_permit module will allow only single concurrent user session for
+      the user with this argument specified and it will attempt to kill all processes
+      of the user after logout.
+    </para>
   </refsect1>
 
   <refsect1 id="pam_selinux_permit-options">
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am
--- Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.kill-user	2008-01-28 18:34:18.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am	2008-01-28 18:35:01.000000000 +0100
@@ -16,10 +16,13 @@ XMLS = README.xml pam_selinux.8.xml pam_
 
 securelibdir = $(SECUREDIR)
 secureconfdir = $(SCONFIGDIR)
+sepermitlockdir = /var/run/sepermit
 
 AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
 	-I$(top_srcdir)/libpam_misc/include \
-	-D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\"
+	-D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\" \
+	-D SEPERMIT_LOCKDIR=\"$(sepermitlockdir)\"
+
 AM_LDFLAGS = -no-undefined \
 	-L$(top_builddir)/libpam -lpam @LIBSELINUX@
 
@@ -34,6 +37,7 @@ endif
 pam_selinux_permit_la_LDFLAGS= $(pam_selinux_la_LDFLAGS)
 
 secureconf_DATA = sepermit.conf
+sepermitlock_DATA =
 
 if HAVE_LIBSELINUX
   securelib_LTLIBRARIES = pam_selinux.la pam_selinux_permit.la
diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf
--- Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf.kill-user	2008-01-28 18:34:18.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf	2008-01-28 18:34:18.000000000 +0100
@@ -4,3 +4,8 @@
 #        - an user name
 #        - a group name, with @group syntax
 #        - a SELinux user name, with %seuser syntax
+# Each line can contain optional arguments separated by :
+# The possible arguments are:
+#        - exclusive - only single login session will
+#          be allowed for the user and the user's processes
+#          will be killed on logout

pam-0.99.8.1-setkeycreatecon.patch:

--- NEW FILE pam-0.99.8.1-setkeycreatecon.patch ---
diff -up Linux-PAM-0.99.8.1/configure.in.setkeycreatecon Linux-PAM-0.99.8.1/configure.in
--- Linux-PAM-0.99.8.1/configure.in.setkeycreatecon	2008-01-28 17:22:40.000000000 +0100
+++ Linux-PAM-0.99.8.1/configure.in	2008-01-28 17:26:25.000000000 +0100
@@ -379,6 +379,7 @@ AC_SUBST(LIBDB)
 AM_CONDITIONAL([HAVE_LIBDB], [test ! -z "$LIBDB"])
 
 AC_CHECK_LIB([nsl],[yp_get_default_domain], LIBNSL="-lnsl", LIBNSL="")
+BACKUP_LIBS=$LIBS
 LIBS="$LIBS $LIBNSL"
 AC_CHECK_FUNCS(yp_get_default_domain)
 LIBS=$BACKUP_LIBS
@@ -396,6 +397,10 @@ AC_SUBST(LIBSELINUX)
 AM_CONDITIONAL([HAVE_LIBSELINUX], [test ! -z "$LIBSELINUX"])
 if test ! -z "$LIBSELINUX" ; then
     AC_DEFINE([WITH_SELINUX], 1, [Defined if SE Linux support is compiled in])
+    BACKUP_LIBS=$LIBS
+    LIBS="$LIBS $LIBSELINUX"
+    AC_CHECK_FUNCS(setkeycreatecon)
+    LIBS=$BACKUP_LIBS
 fi
 
 dnl Checks for header files.
@@ -428,7 +433,7 @@ AC_CHECK_FUNCS(fseeko gethostname gettim
 AC_CHECK_FUNCS(strcspn strdup strspn strstr strtol uname)
 AC_CHECK_FUNCS(getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r)
 AC_CHECK_FUNCS(getgrouplist getline getdelim)
-AC_CHECK_FUNCS(inet_ntop inet_pton ruserok_af setkeycreatecon)
+AC_CHECK_FUNCS(inet_ntop inet_pton ruserok_af)
 
 AC_CHECK_FUNCS(unshare, [UNSHARE=yes], [UNSHARE=no])
 AM_CONDITIONAL([HAVE_UNSHARE], [test "$UNSHARE" = yes])

pam-0.99.8.1-substack.patch:

--- NEW FILE pam-0.99.8.1-substack.patch ---
Index: libpam/pam_dispatch.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_dispatch.c,v
retrieving revision 1.11
diff -u -p -r1.11 pam_dispatch.c
--- libpam/pam_dispatch.c	1 Aug 2006 08:54:57 -0000	1.11
+++ libpam/pam_dispatch.c	12 Oct 2007 16:23:37 -0000
@@ -34,7 +34,8 @@
 static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
 			     _pam_boolean resumed, int use_cached_chain)
 {
-    int depth, impression, status, skip_depth;
+    int depth, impression, status, skip_depth, prev_level, stack_level;
+    struct _pam_substack_state *substates = NULL;
 
     IF_NO_PAMH("_pam_dispatch_aux", pamh, PAM_SYSTEM_ERR);
 
@@ -54,27 +55,51 @@ static int _pam_dispatch_aux(pam_handle_
 	skip_depth = pamh->former.depth;
 	status = pamh->former.status;
 	impression = pamh->former.impression;
+	substates = pamh->former.substates;
 	/* forget all that */
 	pamh->former.impression = _PAM_UNDEF;
 	pamh->former.status = PAM_MUST_FAIL_CODE;
 	pamh->former.depth = 0;
+	pamh->former.substates = NULL;
     } else {
 	skip_depth = 0;
-	impression = _PAM_UNDEF;
-	status = PAM_MUST_FAIL_CODE;
+	substates = malloc(PAM_SUBSTACK_MAX_LEVEL * sizeof(*substates));
+	if (substates == NULL) {
+	    pam_syslog(pamh, LOG_CRIT,
+		       "_pam_dispatch_aux: no memory for substack states");
+	    return PAM_BUF_ERR;
+	}
+	substates[0].impression = impression = _PAM_UNDEF;
+	substates[0].status = status = PAM_MUST_FAIL_CODE;
     }
 
+    prev_level = 0;
+
     /* Loop through module logic stack */
-    for (depth=0 ; h != NULL ; h = h->next, ++depth) {
+    for (depth=0 ; h != NULL ; prev_level = stack_level, h = h->next, ++depth) {
 	int retval, cached_retval, action;
 
+        stack_level = h->stack_level;
+
 	/* skip leading modules if they have already returned */
 	if (depth < skip_depth) {
 	    continue;
 	}
 
+	/* remember state if we are entering a substack */
+	if (prev_level < stack_level) { 
+	    substates[stack_level].impression = impression;
+	    substates[stack_level].status = status;
+	}
+
 	/* attempt to call the module */
-	if (h->func == NULL) {
+	if (h->handler_type == PAM_HT_MUST_FAIL) {
+	    D(("module poorly listed in PAM config; forcing failure"));
+	    retval = PAM_MUST_FAIL_CODE;
+	} else if (h->handler_type == PAM_HT_SUBSTACK) {
+	    D(("skipping substack handler"));
+	    continue;
+	} else if (h->func == NULL) {
 	    D(("module function is not defined, indicating failure"));
 	    retval = PAM_MODULE_UNKNOWN;
 	} else {
@@ -83,10 +108,6 @@ static int _pam_dispatch_aux(pam_handle_
 	    retval = h->func(pamh, flags, h->argc, h->argv);
 	    pamh->mod_name=NULL;
 	    D(("module returned: %s", pam_strerror(pamh, retval)));
-	    if (h->must_fail) {
-		D(("module poorly listed in PAM config; forcing failure"));
-		retval = PAM_MUST_FAIL_CODE;
-	    }
 	}
 
 	/*
@@ -100,6 +121,7 @@ static int _pam_dispatch_aux(pam_handle_
 	    pamh->former.impression = impression;
 	    pamh->former.status = status;
 	    pamh->former.depth = depth;
+	    pamh->former.substates = substates;
 
 	    D(("module %d returned PAM_INCOMPLETE", depth));
 	    return retval;
@@ -176,8 +198,8 @@ static int _pam_dispatch_aux(pam_handle_
 	switch (action) {
 	case _PAM_ACTION_RESET:
 
-	    impression = _PAM_UNDEF;
-	    status = PAM_MUST_FAIL_CODE;
+	    impression = substates[stack_level].impression;
+	    status = substates[stack_level].status;
 	    break;
 
 	case _PAM_ACTION_OK:
@@ -244,9 +266,13 @@ static int _pam_dispatch_aux(pam_handle_
 		}
 
 		/* this means that we need to skip #action stacked modules */
-		do {
- 		    h = h->next;
-		} while ( --action > 0 && h != NULL );
+		while (h->next != NULL && h->next->stack_level >= stack_level && action > 0) {
+ 		    do {
+			h = h->next;
+			++depth;
+		    } while (h->next != NULL && h->next->stack_level > stack_level);
+		    --action;
+		}
 
 		/* note if we try to skip too many modules action is
                    still non-zero and we snag the next if. */
@@ -254,14 +280,19 @@ static int _pam_dispatch_aux(pam_handle_
 
 	    /* this case is a syntax error: we can't succeed */
 	    if (action) {
-		D(("action syntax error"));
+		pam_syslog(pamh, LOG_ERR, "bad jump in stack");
 		impression = _PAM_NEGATIVE;
 		status = PAM_MUST_FAIL_CODE;
 	    }
 	}
-    }
-
+	continue;
+	
 decision_made:     /* by getting  here we have made a decision */
+	while (h->next != NULL && h->next->stack_level >= stack_level) {
+	    h = h->next;
+	    ++depth;
+	}
+    }
 
     /* Sanity check */
     if ( status == PAM_SUCCESS && impression != _PAM_POSITIVE ) {
@@ -269,6 +300,7 @@ decision_made:     /* by getting  here w
 	status = PAM_MUST_FAIL_CODE;
     }
 
+    free(substates);
     /* We have made a decision about the modules executed */
     return status;
 }
Index: libpam/pam_end.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_end.c,v
retrieving revision 1.4
diff -u -p -r1.4 pam_end.c
--- libpam/pam_end.c	12 Jan 2006 10:06:49 -0000	1.4
+++ libpam/pam_end.c	12 Oct 2007 16:23:37 -0000
@@ -71,6 +71,8 @@ int pam_end(pam_handle_t *pamh, int pam_
     _pam_drop(pamh->pam_conversation);
     pamh->fail_delay.delay_fn_ptr = NULL;
 
+    _pam_drop(pamh->former.substates);
+
     /* and finally liberate the memory for the pam_handle structure */
 
     _pam_drop(pamh);
Index: libpam/pam_handlers.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_handlers.c,v
retrieving revision 1.24
diff -u -p -r1.24 pam_handlers.c
--- libpam/pam_handlers.c	14 Jun 2006 11:41:47 -0000	1.24
+++ libpam/pam_handlers.c	12 Oct 2007 16:23:37 -0000
@@ -18,7 +18,7 @@
 
 #define BUF_SIZE                  1024
 #define MODULE_CHUNK              4
-#define UNKNOWN_MODULE_PATH       "<*unknown module path*>"
+#define UNKNOWN_MODULE       "<*unknown module*>"
 #ifndef _PAM_ISA
 #define _PAM_ISA "."
 #endif
@@ -28,7 +28,7 @@ static int _pam_assemble_line(FILE *f, c
 static void _pam_free_handlers_aux(struct handler **hp);
 
 static int _pam_add_handler(pam_handle_t *pamh
-		     , int must_fail, int other, int type
+		     , int must_fail, int other, int stack_level, int type
 		     , int *actions, const char *mod_path
 		     , int argc, char **argv, int argvlen);
 
@@ -43,6 +43,7 @@ static int _pam_add_handler(pam_handle_t
 static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
 				, const char *service /* specific file */
 				, int module_type /* specific type */
+				, int stack_level /* level of substack */
 #ifdef PAM_READ_BOTH_CONFS
 				, int not_other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -51,6 +52,7 @@ static int _pam_load_conf_file(pam_handl
 static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
 				, const char *known_service /* specific file */
 				, int requested_module_type /* specific type */
+				, int stack_level /* level of substack */
 #ifdef PAM_READ_BOTH_CONFS
 				, int not_other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -68,7 +70,7 @@ static int _pam_parse_conf_file(pam_hand
 	int module_type, actions[_PAM_RETURN_VALUES];
 	int other;            /* set if module is for PAM_DEFAULT_SERVICE */
 	int res;              /* module added successfully? */
-	int must_fail=0;      /* a badly formatted line must fail when used */
+	int handler_type = PAM_HT_MODULE; /* regular handler from a module */
 	int argc;
 	char **argv;
 	int argvlen;
@@ -92,6 +94,7 @@ static int _pam_parse_conf_file(pam_hand
 	/* accept "service name" or PAM_DEFAULT_SERVICE modules */
 	if (!strcasecmp(this_service, pamh->service_name) || other) {
 	    int pam_include = 0;
+	    int substack = 0;
 
 	    /* This is a service we are looking for */
 	    D(("_pam_init_handlers: Found PAM config entry for: %s"
@@ -105,7 +108,7 @@ static int _pam_parse_conf_file(pam_hand
 			   "(%s) empty module type", this_service);
 	        module_type = (requested_module_type != PAM_T_ANY) ?
 		  requested_module_type : PAM_T_AUTH;	/* most sensitive */
-	        must_fail = 1; /* install as normal but fail when dispatched */
+	        handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
 	    } else if (!strcasecmp("auth", tok)) {
 		module_type = PAM_T_AUTH;
 	    } else if (!strcasecmp("session", tok)) {
@@ -121,9 +124,9 @@ static int _pam_parse_conf_file(pam_hand
 			   this_service, tok);
 		module_type = (requested_module_type != PAM_T_ANY) ?
 			      requested_module_type : PAM_T_AUTH;	/* most sensitive */
-		must_fail = 1; /* install as normal but fail when dispatched */
+		handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
 	    }
-	    D(("Using %s config entry: %s", must_fail?"BAD ":"", tok));
+	    D(("Using %s config entry: %s", handler_type?"BAD ":"", tok));
 	    if (requested_module_type != PAM_T_ANY &&
 	        module_type != requested_module_type) {
 		D(("Skipping config entry: %s (requested=%d, found=%d)",
@@ -145,7 +148,7 @@ static int _pam_parse_conf_file(pam_hand
 		pam_syslog(pamh, LOG_ERR,
 			   "(%s) no control flag supplied", this_service);
 		_pam_set_default_control(actions, _PAM_ACTION_BAD);
-		must_fail = 1;
+		handler_type = PAM_HT_MUST_FAIL;
 	    } else if (!strcasecmp("required", tok)) {
 		D(("*PAM_F_REQUIRED*"));
 		actions[PAM_SUCCESS] = _PAM_ACTION_OK;
@@ -171,6 +174,11 @@ static int _pam_parse_conf_file(pam_hand
 	    } else if (!strcasecmp("include", tok)) {
 		D(("*PAM_F_INCLUDE*"));
 		pam_include = 1;
+		substack = 0;
+	    } else if (!strcasecmp("substack", tok)) {
+		D(("*PAM_F_SUBSTACK*"));
+		pam_include = 1;
+		substack = 1;
 	    } else {
 		D(("will need to parse %s", tok));
 		_pam_parse_control(actions, tok);
@@ -180,7 +188,18 @@ static int _pam_parse_conf_file(pam_hand
 
 	    tok = _pam_StrTok(NULL, " \n\t", &nexttok);
 	    if (pam_include) {
-		if (_pam_load_conf_file(pamh, tok, this_service, module_type
+	    	if (substack) {
+		    res = _pam_add_handler(pamh, PAM_HT_SUBSTACK, other,
+		    		stack_level, module_type, actions, tok,
+		    		0, NULL, 0);
+		    if (res != PAM_SUCCESS) {
+			pam_syslog(pamh, LOG_ERR, "error adding substack %s", tok);
+			D(("failed to load module - aborting"));
+			return PAM_ABORT;
+		    }  	    
+	    	}
+		if (_pam_load_conf_file(pamh, tok, this_service, module_type,
+		    stack_level + substack
 #ifdef PAM_READ_BOTH_CONFS
 					      , !other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -188,7 +207,7 @@ static int _pam_parse_conf_file(pam_hand
 		    continue;
 		_pam_set_default_control(actions, _PAM_ACTION_BAD);
 		mod_path = NULL;
-		must_fail = 1;
+		handler_type = PAM_HT_MUST_FAIL;
 		nexttok = NULL;
 	    } else if (tok != NULL) {
 		mod_path = tok;
@@ -199,7 +218,7 @@ static int _pam_parse_conf_file(pam_hand
 		pam_syslog(pamh, LOG_ERR,
 		           "(%s) no module name supplied", this_service);
 		mod_path = NULL;
-		must_fail = 1;
+		handler_type = PAM_HT_MUST_FAIL;
 	    }
 
 	    /* nexttok points to remaining arguments... */
@@ -219,7 +238,7 @@ static int _pam_parse_conf_file(pam_hand
 		int y;
 
 		D(("CONF%s: %s%s %d %s %d"
-		   , must_fail?"<*will fail*>":""
+		   , handler_type==PAM_HT_MUST_FAIL?"<*will fail*>":""
 		   , this_service, other ? "(backup)":""
 		   , module_type
 		   , mod_path, argc));
@@ -235,7 +254,7 @@ static int _pam_parse_conf_file(pam_hand
 	    }
 #endif
 
-	    res = _pam_add_handler(pamh, must_fail, other
+	    res = _pam_add_handler(pamh, handler_type, other, stack_level
 				   , module_type, actions, mod_path
 				   , argc, argv, argvlen);
 	    if (res != PAM_SUCCESS) {
@@ -252,6 +271,7 @@ static int _pam_parse_conf_file(pam_hand
 static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
 				, const char *service /* specific file */
 				, int module_type /* specific type */
+				, int stack_level /* level of substack */
 #ifdef PAM_READ_BOTH_CONFS
 				, int not_other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -263,6 +283,12 @@ static int _pam_load_conf_file(pam_handl
 
     D(("_pam_load_conf_file called"));
 
+    if (stack_level >= PAM_SUBSTACK_MAX_LEVEL) {
+	D(("maximum level of substacks reached"));
+	pam_syslog(pamh, LOG_ERR, "maximum level of substacks reached");
+	return PAM_ABORT;
+    }
+
     if (config_name == NULL) {
 	D(("no config file supplied"));
 	pam_syslog(pamh, LOG_ERR, "(%s) no config file supplied", service);
@@ -280,7 +306,7 @@ static int _pam_load_conf_file(pam_handl
     D(("opening %s", config_name));
     f = fopen(config_name, "r");
     if (f != NULL) {
-	retval = _pam_parse_conf_file(pamh, f, service, module_type
+	retval = _pam_parse_conf_file(pamh, f, service, module_type, stack_level
 #ifdef PAM_READ_BOTH_CONFS
 					      , not_other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -379,7 +405,8 @@ int _pam_init_handlers(pam_handle_t *pam
 	    f = fopen(filename, "r");
 	    if (f != NULL) {
 		/* would test magic here? */
-		retval = _pam_parse_conf_file(pamh, f, pamh->service_name, PAM_T_ANY
+		retval = _pam_parse_conf_file(pamh, f, pamh->service_name,
+		    PAM_T_ANY, 0
 #ifdef PAM_READ_BOTH_CONFS
 					      , 0
 #endif /* PAM_READ_BOTH_CONFS */
@@ -400,7 +427,7 @@ int _pam_init_handlers(pam_handle_t *pam
 		D(("checking %s", PAM_CONFIG));
 
 		if ((f = fopen(PAM_CONFIG,"r")) != NULL) {
-		    retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 1);
+		    retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 1);
 		    fclose(f);
 		} else
 #endif /* PAM_READ_BOTH_CONFS */
@@ -419,9 +446,8 @@ int _pam_init_handlers(pam_handle_t *pam
 		f = fopen(PAM_DEFAULT_SERVICE_FILE, "r");
 		if (f != NULL) {
 		    /* would test magic here? */
-		    retval = _pam_parse_conf_file(pamh, f
-						  , PAM_DEFAULT_SERVICE
-						  , PAM_T_ANY
+		    retval = _pam_parse_conf_file(pamh, f, PAM_DEFAULT_SERVICE,
+			PAM_T_ANY, 0
 #ifdef PAM_READ_BOTH_CONFS
 						  , 0
 #endif /* PAM_READ_BOTH_CONFS */
@@ -454,7 +480,7 @@ int _pam_init_handlers(pam_handle_t *pam
 		return PAM_ABORT;
 	    }
 
-	    retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY
+	    retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0
 #ifdef PAM_READ_BOTH_CONFS
 					  , 0
 #endif /* PAM_READ_BOTH_CONFS */
@@ -581,46 +607,19 @@ extract_modulename(const char *mod_path)
   return retval;
 }
 
-int _pam_add_handler(pam_handle_t *pamh
-		     , int must_fail, int other, int type
-		     , int *actions, const char *mod_path
-		     , int argc, char **argv, int argvlen)
+static struct loaded_module *
+_pam_load_module(pam_handle_t *pamh, const char *mod_path)
 {
-    struct loaded_module *mod;
     int x = 0;
-    struct handler **handler_p;
-    struct handler **handler_p2;
-    struct handlers *the_handlers;
-    const char *sym, *sym2;
-    char *mod_full_path=NULL;
+    int success;
 #ifndef PAM_STATIC
     char *mod_full_isa_path=NULL, *isa=NULL;
 #endif
-    servicefn func, func2;
-    int success;
-
-    D(("called."));
-    IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
-
-    /* if NULL set to something that can be searched for */
-    switch (mod_path != NULL) {
-    default:
-	if (mod_path[0] == '/') {
-	    break;
-	}
-	if (asprintf(&mod_full_path, "%s%s",
-		     DEFAULT_MODULE_PATH, mod_path) >= 0) {
-	    mod_path = mod_full_path;
-	    break;
-	}
-	mod_full_path = NULL;
-	pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
-    case 0:
-	mod_path = UNKNOWN_MODULE_PATH;
-    }
+    struct loaded_module *mod;
 
-    D(("_pam_add_handler: adding type %d, module `%s'",type,mod_path));
-    mod  = pamh->handlers.module;
+    D(("_pam_load_module: loading module `%s'", mod_path));
+    
+    mod = pamh->handlers.module;
 
     /* First, ensure the module is loaded */
     while (x < pamh->handlers.modules_used) {
@@ -639,9 +638,8 @@ int _pam_add_handler(pam_handle_t *pamh
 	    if (tmp == NULL) {
 		D(("cannot enlarge module pointer memory"));
 		pam_syslog(pamh, LOG_ERR,
-				"realloc returned NULL in _pam_add_handler");
-		_pam_drop(mod_full_path);
-		return PAM_ABORT;
+				"realloc returned NULL in _pam_load_module");
+		return NULL;
 	    }
 	    pamh->handlers.module = tmp;
 	    pamh->handlers.modules_allocated += MODULE_CHUNK;
@@ -654,10 +652,10 @@ int _pam_add_handler(pam_handle_t *pamh
 	/* Only load static function if function was not found dynamically.
 	 * This code should work even if no dynamic loading is available. */
 	if (success != PAM_SUCCESS) {
-	    D(("_pam_add_handler: open static handler %s", mod_path));
+	    D(("_pam_load_module: open static handler %s", mod_path));
 	    mod->dl_handle = _pam_open_static_handler(pamh, mod_path);
 	    if (mod->dl_handle == NULL) {
-	        D(("_pam_add_handler: unable to find static handler %s",
+	        D(("_pam_load_module: unable to find static handler %s",
 		   mod_path));
 		pam_syslog(pamh, LOG_ERR,
 				"unable to open static handler %s", mod_path);
@@ -670,15 +668,15 @@ int _pam_add_handler(pam_handle_t *pamh
 	    }
 	}
 #else
-	D(("_pam_add_handler: _pam_dlopen(%s)", mod_path));
+	D(("_pam_load_module: _pam_dlopen(%s)", mod_path));
 	mod->dl_handle = _pam_dlopen(mod_path);
-	D(("_pam_add_handler: _pam_dlopen'ed"));
-	D(("_pam_add_handler: dlopen'ed"));
+	D(("_pam_load_module: _pam_dlopen'ed"));
+	D(("_pam_load_module: dlopen'ed"));
 	if (mod->dl_handle == NULL) {
 	    if (strstr(mod_path, "$ISA")) {
 		mod_full_isa_path = malloc(strlen(mod_path) + strlen(_PAM_ISA) + 1);
 		if (mod_full_isa_path == NULL) {
-		    D(("_pam_handler: couldn't get memory for mod_path"));
+		    D(("_pam_load_module: couldn't get memory for mod_path"));
 		    pam_syslog(pamh, LOG_ERR, "no memory for module path");
 		    success = PAM_ABORT;
 		} else {
@@ -694,9 +692,9 @@ int _pam_add_handler(pam_handle_t *pamh
 	    }
 	}
 	if (mod->dl_handle == NULL) {
-	    D(("_pam_add_handler: _pam_dlopen(%s) failed", mod_path));
-	    pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s)", mod_path);
-	    pam_syslog(pamh, LOG_ERR, "[error: %s]", _pam_dlerror());
+	    D(("_pam_load_module: _pam_dlopen(%s) failed", mod_path));
+	    pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s): %s", mod_path,
+	        _pam_dlerror());
 	    /* Don't abort yet; static code may be able to find function.
 	     * But defaults to abort if nothing found below... */
 	} else {
@@ -717,7 +715,7 @@ int _pam_add_handler(pam_handle_t *pamh
 
 	/* indicate its name - later we will search for it by this */
 	if ((mod->name = _pam_strdup(mod_path)) == NULL) {
-	    D(("_pam_handler: couldn't get memory for mod_path"));
+	    D(("_pam_load_module: couldn't get memory for mod_path"));
 	    pam_syslog(pamh, LOG_ERR, "no memory for module path");
 	    success = PAM_ABORT;
 	}
@@ -726,18 +724,54 @@ int _pam_add_handler(pam_handle_t *pamh
 	mod += x;                                    /* the located module */
 	success = PAM_SUCCESS;
     }
+    return success == PAM_SUCCESS ? mod : NULL;
+}
+
+int _pam_add_handler(pam_handle_t *pamh
+		     , int handler_type, int other, int stack_level, int type
+		     , int *actions, const char *mod_path
+		     , int argc, char **argv, int argvlen)
+{
+    struct loaded_module *mod = NULL;
+    struct handler **handler_p;
+    struct handler **handler_p2;
+    struct handlers *the_handlers;
+    const char *sym, *sym2;
+    char *mod_full_path;
+    servicefn func, func2;
+    int mod_type = PAM_MT_FAULTY_MOD;
+
+    D(("called."));
+    IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
 
-    _pam_drop(mod_full_path);
-    mod_path = NULL;                        /* no longer needed or trusted */
+    D(("_pam_add_handler: adding type %d, handler_type %d, module `%s'",
+	type, handler_type, mod_path));
 
-    /* Now return error if necessary after trying all possible ways... */
-    if (success != PAM_SUCCESS)
-	return(success);
+    if (handler_type == PAM_HT_MODULE && mod_path != NULL) {
+	if (mod_path[0] == '/') {
+	    mod = _pam_load_module(pamh, mod_path);
+	} else if (asprintf(&mod_full_path, "%s%s",
+			     DEFAULT_MODULE_PATH, mod_path) >= 0) {
+	    mod = _pam_load_module(pamh, mod_full_path);
+	    _pam_drop(mod_full_path);
+	} else {
+	    pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
+	    return PAM_ABORT;
+	}
+
+	if (mod == NULL) {
+	    /* if we get here with NULL it means allocation error */
+	    return PAM_ABORT;
+	}
+	
+	mod_type = mod->type;
+    }
+    
+    if (mod_path == NULL)
+    	mod_path = UNKNOWN_MODULE;
 
     /*
-     * At this point 'mod' points to the stored/loaded module. If its
-     * dl_handle is unknown, then we must be able to indicate dispatch
-     * failure with 'must_fail'
+     * At this point 'mod' points to the stored/loaded module.
      */
 
     /* Now define the handler(s) based on mod->dlhandle and type */
@@ -780,43 +814,43 @@ int _pam_add_handler(pam_handle_t *pamh
     /* are the modules reliable? */
     if (
 #ifdef PAM_STATIC
-	 mod->type != PAM_MT_STATIC_MOD
+	 mod_type != PAM_MT_STATIC_MOD
 	 &&
 #else
-	 mod->type != PAM_MT_DYNAMIC_MOD
+	 mod_type != PAM_MT_DYNAMIC_MOD
 	 &&
 #endif
-	 mod->type != PAM_MT_FAULTY_MOD
+	 mod_type != PAM_MT_FAULTY_MOD
 	) {
-	D(("_pam_add_handlers: illegal module library type; %d", mod->type));
+	D(("_pam_add_handlers: illegal module library type; %d", mod_type));
 	pam_syslog(pamh, LOG_ERR,
 			"internal error: module library type not known: %s;%d",
-			sym, mod->type);
+			sym, mod_type);
 	return PAM_ABORT;
     }
 
     /* now identify this module's functions - for non-faulty modules */
 
 #ifdef PAM_STATIC
-    if ((mod->type == PAM_MT_STATIC_MOD) &&
+    if ((mod_type == PAM_MT_STATIC_MOD) &&
         (func = (servicefn)_pam_get_static_sym(mod->dl_handle, sym)) == NULL) {
 	pam_syslog(pamh, LOG_ERR, "unable to resolve static symbol: %s", sym);
     }
 #else
-    if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
+    if ((mod_type == PAM_MT_DYNAMIC_MOD) &&
         !(func = _pam_dlsym(mod->dl_handle, sym)) ) {
 	pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym);
     }
 #endif
     if (sym2) {
 #ifdef PAM_STATIC
-	if ((mod->type == PAM_MT_STATIC_MOD) &&
+	if ((mod_type == PAM_MT_STATIC_MOD) &&
 	    (func2 = (servicefn)_pam_get_static_sym(mod->dl_handle, sym2))
 	    == NULL) {
 	    pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym2);
 	}
 #else
-	if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
+	if ((mod_type == PAM_MT_DYNAMIC_MOD) &&
 	    !(func2 = _pam_dlsym(mod->dl_handle, sym2)) ) {
 	    pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym2);
 	}
@@ -835,14 +869,15 @@ int _pam_add_handler(pam_handle_t *pamh
 	return (PAM_ABORT);
     }
 
-    (*handler_p)->must_fail = must_fail;        /* failure forced? */
+    (*handler_p)->handler_type = handler_type;
+    (*handler_p)->stack_level = stack_level;
     (*handler_p)->func = func;
     memcpy((*handler_p)->actions,actions,sizeof((*handler_p)->actions));
     (*handler_p)->cached_retval = _PAM_INVALID_RETVAL;
     (*handler_p)->cached_retval_p = &((*handler_p)->cached_retval);
     (*handler_p)->argc = argc;
     (*handler_p)->argv = argv;                       /* not a copy */
-    (*handler_p)->mod_name = extract_modulename(mod->name);
+    (*handler_p)->mod_name = extract_modulename(mod_path);
     (*handler_p)->next = NULL;
 
     /* some of the modules have a second calling function */
@@ -857,7 +892,8 @@ int _pam_add_handler(pam_handle_t *pamh
 	    return (PAM_ABORT);
 	}
 
-	(*handler_p2)->must_fail = must_fail;        /* failure forced? */
+	(*handler_p2)->handler_type = handler_type;
+	(*handler_p2)->stack_level = stack_level;
 	(*handler_p2)->func = func2;
 	memcpy((*handler_p2)->actions,actions,sizeof((*handler_p2)->actions));
 	(*handler_p2)->cached_retval =  _PAM_INVALID_RETVAL;     /* ignored */
@@ -873,7 +909,7 @@ int _pam_add_handler(pam_handle_t *pamh
 	} else {
 	    (*handler_p2)->argv = NULL;              /* no arguments */
 	}
-	(*handler_p2)->mod_name = extract_modulename(mod->name);
+	(*handler_p2)->mod_name = extract_modulename(mod_path);
 	(*handler_p2)->next = NULL;
     }
 
Index: libpam/pam_private.h
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_private.h,v
retrieving revision 1.19
diff -u -p -r1.19 pam_private.h
--- libpam/pam_private.h	24 Jul 2006 15:47:40 -0000	1.19
+++ libpam/pam_private.h	12 Oct 2007 16:23:37 -0000
@@ -44,7 +44,7 @@
 #define _PAM_INVALID_RETVAL  -1    /* default value for cached_retval */
 
 struct handler {
-    int must_fail;
+    int handler_type;
     int (*func)(pam_handle_t *pamh, int flags, int argc, char **argv);
     int actions[_PAM_RETURN_VALUES];
     /* set by authenticate, open_session, chauthtok(1st)
@@ -54,8 +54,13 @@ struct handler {
     char **argv;
     struct handler *next;
     char *mod_name;
+    int stack_level;
 };
 
+#define PAM_HT_MODULE       0
+#define PAM_HT_MUST_FAIL    1
+#define PAM_HT_SUBSTACK     2
+
 struct loaded_module {
     char *name;
     int type; /* PAM_STATIC_MOD or PAM_DYNAMIC_MOD */
@@ -76,7 +81,7 @@ struct handlers {
 };
 
 struct service {
-    struct loaded_module *module; /* Only used for dynamic loading */
+    struct loaded_module *module; /* Array of modules */
     int modules_allocated;
     int modules_used;
     int handlers_loaded;
@@ -111,6 +116,12 @@ struct _pam_fail_delay {
     const void *delay_fn_ptr;
 };
 
+/* initial state in substack */
+struct _pam_substack_state {
+    int impression;
+    int status;
+};
+
 struct _pam_former_state {
 /* this is known and set by _pam_dispatch() */
     int choice;            /* which flavor of module function did we call? */
@@ -119,6 +130,7 @@ struct _pam_former_state {
     int depth;             /* how deep in the stack were we? */
     int impression;        /* the impression at that time */
     int status;            /* the status before returning incomplete */
+    struct _pam_substack_state *substates; /* array of initial substack states */
 
 /* state info used by pam_get_user() function */
     int fail_user;
@@ -175,6 +187,8 @@ struct pam_handle {
 #define _PAM_ACTION_UNDEF      -6   /* this is treated as an error
 				       ( = _PAM_ACTION_BAD) */
 
+#define PAM_SUBSTACK_MAX_LEVEL 16   /* maximum level of substacks */
+
 /* character tables for parsing config files */
 extern const char * const _pam_token_actions[-_PAM_ACTION_UNDEF];
 extern const char * const _pam_token_returns[_PAM_RETURN_VALUES+1];
Index: libpam/pam_start.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_start.c,v
retrieving revision 1.9
diff -u -p -r1.9 pam_start.c
--- libpam/pam_start.c	24 Jul 2006 15:47:40 -0000	1.9
+++ libpam/pam_start.c	12 Oct 2007 16:23:37 -0000
@@ -88,6 +88,7 @@ int pam_start (
     (*pamh)->oldauthtok = NULL;
     (*pamh)->fail_delay.delay_fn_ptr = NULL;
     (*pamh)->former.choice = PAM_NOT_STACKED;
+    (*pamh)->former.substates = NULL;
 #ifdef HAVE_LIBAUDIT
     (*pamh)->audit_state = 0;
 #endif
Index: doc/man/pam.conf-syntax.xml
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/doc/man/pam.conf-syntax.xml,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- doc/man/pam.conf-syntax.xml	26 Aug 2007 22:44:51 -0000	1.4
+++ doc/man/pam.conf-syntax.xml	19 Oct 2007 17:06:30 -0000	1.5
@@ -180,6 +180,24 @@
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term>substack</term>
+        <listitem>
+          <para>
+            include all lines of given type from the configuration
+            file specified as an argument to this control. This differs from
+            <emphasis>include</emphasis> in that evaluation of the
+            <emphasis>done</emphasis> and <emphasis>die</emphasis> actions
+            in a substack does not cause skipping the rest of the complete
+            module stack, but only of the substack. Jumps in a substack
+            also can not make evaluation jump out of it, and the whole substack
+            is counted as one module when the jump is done in a parent stack.
+            The <emphasis>reset</emphasis> action will reset the state of a
+            module stack to the state it was in as of beginning of the substack
+            evaluation.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
 
     <para>

pam-0.99.8.1-tty-audit.patch:

--- NEW FILE pam-0.99.8.1-tty-audit.patch ---
Written-by: Miloslav Trmac <mitr at redhat.com>
Reviewed-by: Tomas Mraz <tmraz at redhat.com>
diff -urN Linux-PAM/configure.in Linux-PAM-0.99.8.1/configure.in
--- Linux-PAM/configure.in	2007-11-28 13:41:14.000000000 +0100
+++ Linux-PAM-0.99.8.1/configure.in	2007-11-28 14:35:30.000000000 +0100
@@ -331,7 +331,11 @@
         WITH_LIBAUDIT=$enableval, WITH_LIBAUDIT=yes)
 if test x"$WITH_LIBAUDIT" != xno ; then
         AC_CHECK_HEADER([libaudit.h],
-              [AC_CHECK_LIB(audit, audit_log_acct_message, LIBAUDIT=-laudit, LIBAUDIT="")]
+              [AC_CHECK_LIB(audit, audit_log_acct_message, LIBAUDIT=-laudit, LIBAUDIT="")
+	       AC_CHECK_TYPE([struct audit_tty_status],
+		             [HAVE_AUDIT_TTY_STATUS=yes],
+			     [HAVE_AUDIT_TTY_STATUS=""],
+			     [#include <libaudit.h>])]
         )
         if test ! -z "$LIBAUDIT" -a "ac_cv_header_libaudit_h" != "no" ; then
             AC_DEFINE([HAVE_LIBAUDIT], 1, [Defined if audit support should be compiled in])
@@ -340,6 +344,8 @@
 	LIBAUDIT=""
 fi
 AC_SUBST(LIBAUDIT)
+AM_CONDITIONAL([HAVE_AUDIT_TTY_STATUS],
+	       [test "x$HAVE_AUDIT_TTY_STATUS" = xyes])
 
 BACKUP_LIBS=$LIBS
 AC_SEARCH_LIBS([crypt],[xcrypt crypt], LIBCRYPT="-l$ac_lib", LIBCRYPT="")
@@ -517,7 +523,8 @@
 	modules/pam_securetty/Makefile modules/pam_selinux/Makefile \
 	modules/pam_shells/Makefile modules/pam_stress/Makefile \
 	modules/pam_succeed_if/Makefile modules/pam_tally/Makefile \
-	modules/pam_time/Makefile modules/pam_umask/Makefile \
+	modules/pam_time/Makefile modules/pam_tty_audit/Makefile \
+	modules/pam_umask/Makefile \
 	modules/pam_unix/Makefile modules/pam_userdb/Makefile \
 	modules/pam_warn/Makefile modules/pam_wheel/Makefile \
 	modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile \
diff -urN Linux-PAM/modules/Makefile.am Linux-PAM-0.99.8.1/modules/Makefile.am
--- Linux-PAM/modules/Makefile.am	2007-11-28 13:41:13.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/Makefile.am	2007-11-28 14:02:48.000000000 +0100
@@ -9,8 +9,8 @@
 	pam_lastlog pam_limits pam_listfile pam_localuser pam_mail \
 	pam_mkhomedir pam_motd pam_nologin pam_permit pam_rhosts pam_rootok \
 	pam_securetty pam_selinux pam_shells pam_stress pam_succeed_if \
-	pam_tally pam_time pam_umask pam_unix pam_userdb pam_warn \
-	pam_wheel pam_xauth pam_exec pam_namespace pam_loginuid \
+	pam_tally pam_time pam_tty_audit pam_umask pam_unix pam_userdb \
+	pam_warn pam_wheel pam_xauth pam_exec pam_namespace pam_loginuid \
 	pam_faildelay
 
 CLEANFILES = *~
diff -urN Linux-PAM/modules/pam_tty_audit/Makefile.am Linux-PAM-0.99.8.1/modules/pam_tty_audit/Makefile.am
--- Linux-PAM/modules/pam_tty_audit/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/Makefile.am	2007-11-28 16:05:00.000000000 +0100
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk at suse.de>
+#
+
+CLEANFILES = *~
+
+EXTRA_DIST = README ${MANS} $(XMLS)
+
+man_MANS = pam_tty_audit.8
+XMLS = README.xml pam_tty_audit.8.xml
+
+securelibdir = $(SECUREDIR)
+
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
+AM_LDFLAGS = -no-undefined -avoid-version -module \
+	-L$(top_builddir)/libpam -lpam
+if HAVE_VERSIONING
+  AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+endif
+
+if HAVE_AUDIT_TTY_STATUS
+  securelib_LTLIBRARIES = pam_tty_audit.la
+endif
+
+if ENABLE_REGENERATE_MAN
+noinst_DATA = README
+README: pam_tty_audit.8.xml
+-include $(top_srcdir)/Make.xml.rules
+endif
+
diff -urN Linux-PAM/modules/pam_tty_audit/pam_tty_audit.c Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c
--- Linux-PAM/modules/pam_tty_audit/pam_tty_audit.c	1970-01-01 01:00:00.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c	2007-11-28 16:10:43.000000000 +0100
@@ -0,0 +1,332 @@
+/* Copyright © 2007 Red Hat, Inc. All rights reserved.
+   Red Hat author: Miloslav Trmač <mitr at redhat.com>
+
+   Redistribution and use in source and binary forms of Linux-PAM, with
+   or without modification, are permitted provided that the following
+   conditions are met:
+
+   1. Redistributions of source code must retain any existing copyright
+      notice, and this entire permission notice in its entirety,
+      including the disclaimer of warranties.
+
+   2. Redistributions in binary form must reproduce all prior and current
+      copyright notices, this list of conditions, and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+   3. The name of any author may not be used to endorse or promote
+      products derived from this software without their specific prior
+      written permission.
+
+   ALTERNATIVELY, this product may be distributed under the terms of the
+   GNU General Public License, in which case the provisions of the GNU
+   GPL are required INSTEAD OF the above restrictions.  (This clause is
+   necessary due to a potential conflict between the GNU 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(S) 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. */
+
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <libaudit.h>
+#include <linux/netlink.h>
+#include <security/pam_ext.h>
+#include <security/pam_modules.h>
+#include <security/pam_modutil.h>
+
+#define DATANAME "pam_tty_audit_last_state"
+
+/* Open an audit netlink socket */
+static int
+nl_open (void)
+{
+  return socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
+}
+
+static int
+nl_send (int fd, unsigned type, unsigned flags, const void *data, size_t size)
+{
+  struct sockaddr_nl addr;
+  struct msghdr msg;
+  struct nlmsghdr nlm;
+  struct iovec iov[2];
+  ssize_t res;
+
+  nlm.nlmsg_len = NLMSG_LENGTH (size);
+  nlm.nlmsg_type = type;
+  nlm.nlmsg_flags = NLM_F_REQUEST | flags;
+  nlm.nlmsg_seq = 0;
+  nlm.nlmsg_pid = 0;
+  iov[0].iov_base = &nlm;
+  iov[0].iov_len = sizeof (nlm);
+  iov[1].iov_base = (void *)data;
+  iov[1].iov_len = size;
+  addr.nl_family = AF_NETLINK;
+  addr.nl_pid = 0;
+  addr.nl_groups = 0;
+  msg.msg_name = &addr;
+  msg.msg_namelen = sizeof (addr);
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 2;
+  msg.msg_control = NULL;
+  msg.msg_controllen = 0;
+  msg.msg_flags = 0;
+  res = sendmsg (fd, &msg, 0);
+  if (res == -1)
+    return -1;
+  if ((size_t)res != nlm.nlmsg_len)
+    {
+      errno = EIO;
+      return -1;
+    }
+  return 0;
+}
+
+static int
+nl_recv (int fd, unsigned type, void *buf, size_t size)
+{
+  struct sockaddr_nl addr;
+  struct msghdr msg;
+  struct nlmsghdr nlm;
+  struct iovec iov[2];
+  ssize_t res;
+
+ again:
+  iov[0].iov_base = &nlm;
+  iov[0].iov_len = sizeof (nlm);
+  msg.msg_name = &addr;
+  msg.msg_namelen = sizeof (addr);
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 1;
+  msg.msg_control = NULL;
+  msg.msg_controllen = 0;
+  if (type != NLMSG_ERROR)
+    {
+      res = recvmsg (fd, &msg, MSG_PEEK);
+      if (res == -1)
+	return -1;
+      if (res != NLMSG_LENGTH (0))
+	{
+	  errno = EIO;
+	  return -1;
+	}
+      if (nlm.nlmsg_type == NLMSG_ERROR)
+	{
+	  struct nlmsgerr err;
+
+	  iov[1].iov_base = &err;
+	  iov[1].iov_len = sizeof (err);
+	  msg.msg_iovlen = 2;
+	  res = recvmsg (fd, &msg, 0);
+	  if (res == -1)
+	    return -1;
+	  if ((size_t)res != NLMSG_LENGTH (sizeof (err))
+	      || nlm.nlmsg_type != NLMSG_ERROR)
+	    {
+	      errno = EIO;
+	      return -1;
+	    }
+	  if (err.error == 0)
+	    goto again;
+	  errno = -err.error;
+	  return -1;
+	}
+    }
+  if (size != 0)
+    {
+      iov[1].iov_base = buf;
+      iov[1].iov_len = size;
+      msg.msg_iovlen = 2;
+    }
+  res = recvmsg (fd, &msg, 0);
+  if (res == -1)
+    return -1;
+  if ((size_t)res != NLMSG_LENGTH (size)
+      || nlm.nlmsg_type != type)
+    {
+      errno = EIO;
+      return -1;
+    }
+  return 0;
+}
+
+static int
+nl_recv_ack (int fd)
+{
+  struct nlmsgerr err;
+
+  if (nl_recv (fd, NLMSG_ERROR, &err, sizeof (err)) != 0)
+    return -1;
+  if (err.error != 0)
+    {
+      errno = -err.error;
+      return -1;
+    }
+  return 0;
+}
+
+static void
+cleanup_old_status (pam_handle_t *pamh, void *data, int error_status)
+{
+  (void)pamh;
+  (void)error_status;
+  free (data);
+}
+
+int
+pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+  enum command { CMD_NONE, CMD_ENABLE, CMD_DISABLE };
+
+  enum command command;
+  struct audit_tty_status *old_status, new_status;
+  const char *user;
+  uid_t user_uid;
+  struct passwd *pwd;
+  int i, fd;
+
+  (void)flags;
+
+  if (pam_get_user (pamh, &user, NULL) != PAM_SUCCESS)
+    {
+      pam_syslog (pamh, LOG_ERR, "error determining target user's name");
+      return PAM_SESSION_ERR;
+    }
+  pwd = pam_modutil_getpwnam (pamh, user);
+  if (pwd == NULL)
+    {
+      pam_syslog (pamh, LOG_ERR, "error determining target user's UID: %m");
+      return PAM_SESSION_ERR;
+    }
+  user_uid = pwd->pw_uid;
+
+  command = CMD_NONE;
+  for (i = 0; i < argc; i++)
+    {
+      if (strncmp (argv[i], "enable=", 7) == 0
+	  || strncmp (argv[i], "disable=", 8) == 0)
+	{
+	  enum command this_command;
+	  char *copy, *tok_data, *tok;
+
+	  this_command = *argv[i] == 'e' ? CMD_ENABLE : CMD_DISABLE;
+	  copy = strdup (strchr (argv[i], '=') + 1);
+	  if (copy == NULL)
+	    return PAM_SESSION_ERR;
+	  for (tok = strtok_r (copy, ",", &tok_data); tok != NULL;
+	       tok = strtok_r (NULL, ",", &tok_data))
+	    {
+	      pwd = pam_modutil_getpwnam (pamh, tok);
+	      if (pwd == NULL)
+		{
+		  pam_syslog (pamh, LOG_WARNING, "unknown user %s", tok);
+		  continue;
+		}
+	      if (pwd->pw_uid == user_uid)
+		{
+		  command = this_command;
+		  break;
+		}
+	    }
+	  free (copy);
+	}
+    }
+  if (command == CMD_NONE)
+    return PAM_SUCCESS;
+
+  old_status = malloc (sizeof (*old_status));
+  if (old_status == NULL)
+    return PAM_SESSION_ERR;
+
+  fd = nl_open ();
+  if (fd == -1
+      || nl_send (fd, AUDIT_TTY_GET, 0, NULL, 0) != 0
+      || nl_recv (fd, AUDIT_TTY_GET, old_status, sizeof (*old_status)) != 0)
+    {
+      pam_syslog (pamh, LOG_ERR, "error reading current audit status: %m");
+      if (fd != -1)
+	close (fd);
+      free (old_status);
+      return PAM_SESSION_ERR;
+    }
+
+  if (old_status->enabled == (command == CMD_ENABLE ? 1 : 0))
+    {
+      free (old_status);
+      goto ok_fd;
+    }
+
+  if (pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
+      != PAM_SUCCESS)
+    {
+      pam_syslog (pamh, LOG_ERR, "error saving old audit status");
+      close (fd);
+      free (old_status);
+      return PAM_SESSION_ERR;
+    }
+
+  new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
+  if (nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, &new_status,
+	       sizeof (new_status)) != 0
+      || nl_recv_ack (fd) != 0)
+    {
+      pam_syslog (pamh, LOG_ERR, "error setting current audit status: %m");
+      close (fd);
+      return PAM_SESSION_ERR;
+    }
+  /* Fall through */
+ ok_fd:
+  close (fd);
+  pam_syslog (pamh, LOG_DEBUG, "changed status from %d to %d",
+	      old_status->enabled, new_status.enabled);
+  return PAM_SUCCESS;
+}
+
+int
+pam_sm_close_session (pam_handle_t *pamh, int flags, int argc,
+		      const char **argv)
+{
+  const void *status_;
+
+  (void)flags;
+  (void)argc;
+  (void)argv;
+  if (pam_get_data (pamh, DATANAME, &status_) == PAM_SUCCESS)
+    {
+      const struct audit_tty_status *status;
+      int fd;
+
+      status = status_;
+
+      fd = nl_open ();
+      if (fd == -1
+	  || nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, status,
+		      sizeof (*status)) != 0
+	  || nl_recv_ack (fd) != 0)
+	{
+	  pam_syslog (pamh, LOG_ERR, "error restoring audit status: %m");
+	  if (fd != -1)
+	    close (fd);
+	  return PAM_SESSION_ERR;
+	}
+      close (fd);
+      pam_syslog (pamh, LOG_ERR, "restored status to %d", status->enabled);
+    }
+  return PAM_SUCCESS;
+}
diff -urN Linux-PAM/modules/pam_tty_audit/pam_tty_audit.8.xml Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml
--- Linux-PAM/modules/pam_tty_audit/pam_tty_audit.8.xml	1970-01-01 01:00:00.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml	2007-11-28 15:50:22.000000000 +0100
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+	"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+<refentry id="pam_tty_audit">
+
+  <refmeta>
+    <refentrytitle>pam_tty_audit</refentrytitle>
+    <manvolnum>8</manvolnum>
+    <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+  </refmeta>
+
+  <refnamediv id="pam_tty_audit-name">
+    <refname>pam_tty_audit</refname>
+    <refpurpose>Enable or disable TTY auditing for specified users</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis id="pam_tty_audit-cmdsynopsis">
+      <command>pam_tty_audit.so</command>
+      <arg choice="opt">
+	disable=<replaceable>usernames</replaceable>
+      </arg>
+      <arg choice="opt">
+	enable=<replaceable>usernames</replaceable>
+      </arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1 id="pam_tty_audit-description">
+    <title>DESCRIPTION</title>
+    <para>
+      The pam_tty_audit PAM module is used to enable or disable TTY auditing.
+      By default, the kernel does not audit input on any TTY.
+    </para>
+  </refsect1>
+
+  <refsect1 id="pam_tty_audit-options">
+    <title>OPTIONS</title>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <option>disable=<replaceable>usernames</replaceable></option>
+        </term>
+        <listitem>
+          <para>
+	    For each user matching one of comma-separated
+	    <option><replaceable>usernames</replaceable></option>, disable
+	    TTY auditing.  This overrides any older <option>enable</option>
+	    option for the same user name.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <option>enable=<replaceable>usernames</replaceable></option>
+        </term>
+        <listitem>
+          <para>
+	    For each user matching one of comma-separated
+	    <option><replaceable>usernames</replaceable></option>, enable
+	    TTY auditing.  This overrides any older <option>disable</option>
+	    option for the same user name.
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1 id="pam_tty_audit-services">
+    <title>MODULE SERVICES PROVIDED</title>
+    <para>
+      Only the <emphasis remap='B'>session</emphasis> service is supported.
+    </para>
+  </refsect1>
+
+  <refsect1 id='pam_tty_audit-return_values'>
+    <title>RETURN VALUES</title>
+    <variablelist>
+      <varlistentry>
+        <term>PAM_SESSION_ERR</term>
+        <listitem>
+           <para>
+	     Error reading or modifying the TTY audit flag.  See the system log
+	     for more details.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>PAM_SUCCESS</term>
+        <listitem>
+          <para>
+            Success.
+          </para>
+        </listitem>
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <refsect1 id='pam_tty_audit-examples'>
+    <title>EXAMPLES</title>
+    <para>
+      Audit all administrative actions.
+      <programlisting>
+login   root     required       pam_tty_audit.so enable=root
+su      root     required       pam_tty_audit.so enable=root
+su-l    root     required       pam_tty_audit.so enable=root
+sudo    root     required       pam_tty_audit.so enable=root
+sudo-l  root     required       pam_tty_audit.so enable=root
+sshd    root     required       pam_tty_audit.so enable=root
+      </programlisting>
+    </para>
+  </refsect1>
+
+  <refsect1 id='pam_tty_audit-author'>
+    <title>AUTHOR</title>
+      <para>
+        pam_tty_audit was written by Miloslav Trmač
+	<mitr at redhat.com>.
+      </para>
+  </refsect1>
+
+</refentry>
diff -urN Linux-PAM/modules/pam_tty_audit/README.xml Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml
--- Linux-PAM/modules/pam_tty_audit/README.xml	1970-01-01 01:00:00.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml	2007-11-28 15:52:50.000000000 +0100
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.docbook.org/xml/4.3/docbookx.dtd">
+
+<article>
+
+  <articleinfo>
+
+    <title>
+      <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+      href="pam_tty_audit.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_tty_audit-name"]/*)'/>
+    </title>
+
+  </articleinfo>
+
+  <section>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+      href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-description"]/*)'/>
+  </section>
+
+  <section>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+      href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-options"]/*)'/>
+  </section>
+
+  <section>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+      href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-examples"]/*)'/>
+  </section>
+
+  <section>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+      href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-author"]/*)'/>
+  </section>
+
+</article>

pam-0.99.8.1-tty-audit2.patch:

--- NEW FILE pam-0.99.8.1-tty-audit2.patch ---
Written-by: Miloslav Trmac <mitr at redhat.com>
Reviewed-by: Tomas Mraz <tmraz at redhat.com>
diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml
--- Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml.tty-audit2	2008-01-02 11:28:26.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml	2008-01-02 11:29:55.000000000 +0100
@@ -19,10 +19,10 @@
     <cmdsynopsis id="pam_tty_audit-cmdsynopsis">
       <command>pam_tty_audit.so</command>
       <arg choice="opt">
-	disable=<replaceable>usernames</replaceable>
+	disable=<replaceable>patterns</replaceable>
       </arg>
       <arg choice="opt">
-	enable=<replaceable>usernames</replaceable>
+	enable=<replaceable>patterns</replaceable>
       </arg>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -40,27 +40,40 @@
     <variablelist>
       <varlistentry>
         <term>
-          <option>disable=<replaceable>usernames</replaceable></option>
+          <option>disable=<replaceable>patterns</replaceable></option>
         </term>
         <listitem>
           <para>
-	    For each user matching one of comma-separated
-	    <option><replaceable>usernames</replaceable></option>, disable
-	    TTY auditing.  This overrides any older <option>enable</option>
-	    option for the same user name.
+	    For each user matching one of comma-separated glob
+	    <option><replaceable>patterns</replaceable></option>, disable
+	    TTY auditing.  This overrides any previous <option>enable</option>
+	    option matchin the same user name on the command line.
           </para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term>
-          <option>enable=<replaceable>usernames</replaceable></option>
+          <option>enable=<replaceable>patterns</replaceable></option>
         </term>
         <listitem>
           <para>
-	    For each user matching one of comma-separated
-	    <option><replaceable>usernames</replaceable></option>, enable
-	    TTY auditing.  This overrides any older <option>disable</option>
-	    option for the same user name.
+	    For each user matching one of comma-separated glob
+	    <option><replaceable>patterns</replaceable></option>, enable
+	    TTY auditing.  This overrides any previous <option>disable</option>
+	    option matching the same user name on the command line.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <option>open_only</option>
+        </term>
+        <listitem>
+          <para>
+           Set the TTY audit flag when opening the session, but do not restore
+           it when closing the session.  Using this option is necessary for
+           some services that don't <function>fork()</function> to run the
+           authenticated session, such as <command>sudo</command>.
           </para>
         </listitem>
       </varlistentry>
@@ -99,17 +112,24 @@
     </variablelist>
   </refsect1>
 
+  <refsect1 id='pam_tty_audit-notes'>
+    <title>NOTES</title>
+    <para>
+      When TTY auditing is enabled, it is inherited by all processes started by
+      that user.  In particular, daemons restarted by an user will still have
+      TTY auditing enabled, and audit TTY input even by other users unless
+      auditing for these users is explicitly disabled.  Therefore, it is
+      recommended to use <option>disable=*</option> as the first option for
+      most daemons using PAM.
+    </para>
+  </refsect1>
+
   <refsect1 id='pam_tty_audit-examples'>
     <title>EXAMPLES</title>
     <para>
       Audit all administrative actions.
       <programlisting>
-login   root     required       pam_tty_audit.so enable=root
-su      root     required       pam_tty_audit.so enable=root
-su-l    root     required       pam_tty_audit.so enable=root
-sudo    root     required       pam_tty_audit.so enable=root
-sudo-l  root     required       pam_tty_audit.so enable=root
-sshd    root     required       pam_tty_audit.so enable=root
+session	required pam_tty_audit.so disable=* enable=root
       </programlisting>
     </para>
   </refsect1>
diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml
--- Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml.tty-audit2	2008-01-02 11:28:26.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml	2008-01-02 11:28:26.000000000 +0100
@@ -25,6 +25,11 @@
 
   <section>
     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+      href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-notes"]/*)'/>
+  </section>
+
+  <section>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
       href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-examples"]/*)'/>
   </section>
 
diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c
--- Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c.tty-audit2	2008-01-02 11:28:26.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c	2008-01-02 11:28:26.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright © 2007 Red Hat, Inc. All rights reserved.
+/* Copyright © 2007, 2008 Red Hat, Inc. All rights reserved.
    Red Hat author: Miloslav Trmač <mitr at redhat.com>
 
    Redistribution and use in source and binary forms of Linux-PAM, with
@@ -37,7 +37,7 @@
    DAMAGE. */
 
 #include <errno.h>
-#include <pwd.h>
+#include <fnmatch.h>
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
@@ -197,9 +197,7 @@ pam_sm_open_session (pam_handle_t *pamh,
   enum command command;
   struct audit_tty_status *old_status, new_status;
   const char *user;
-  uid_t user_uid;
-  struct passwd *pwd;
-  int i, fd;
+  int i, fd, open_only;
 
   (void)flags;
 
@@ -208,15 +206,9 @@ pam_sm_open_session (pam_handle_t *pamh,
       pam_syslog (pamh, LOG_ERR, "error determining target user's name");
       return PAM_SESSION_ERR;
     }
-  pwd = pam_modutil_getpwnam (pamh, user);
-  if (pwd == NULL)
-    {
-      pam_syslog (pamh, LOG_ERR, "error determining target user's UID: %m");
-      return PAM_SESSION_ERR;
-    }
-  user_uid = pwd->pw_uid;
 
   command = CMD_NONE;
+  open_only = 0;
   for (i = 0; i < argc; i++)
     {
       if (strncmp (argv[i], "enable=", 7) == 0
@@ -232,13 +224,7 @@ pam_sm_open_session (pam_handle_t *pamh,
 	  for (tok = strtok_r (copy, ",", &tok_data); tok != NULL;
 	       tok = strtok_r (NULL, ",", &tok_data))
 	    {
-	      pwd = pam_modutil_getpwnam (pamh, tok);
-	      if (pwd == NULL)
-		{
-		  pam_syslog (pamh, LOG_WARNING, "unknown user %s", tok);
-		  continue;
-		}
-	      if (pwd->pw_uid == user_uid)
+	      if (fnmatch (tok, user, 0) == 0)
 		{
 		  command = this_command;
 		  break;
@@ -246,6 +232,13 @@ pam_sm_open_session (pam_handle_t *pamh,
 	    }
 	  free (copy);
 	}
+      else if (strcmp (argv[i], "open_only") == 0)
+	open_only = 1;
+      else
+	{
+	  pam_syslog (pamh, LOG_ERR, "unknown option `%s'", argv[i]);
+	  return PAM_SESSION_ERR;
+	}
     }
   if (command == CMD_NONE)
     return PAM_SUCCESS;
@@ -266,13 +259,15 @@ pam_sm_open_session (pam_handle_t *pamh,
       return PAM_SESSION_ERR;
     }
 
-  if (old_status->enabled == (command == CMD_ENABLE ? 1 : 0))
+  new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
+  if (old_status->enabled == new_status.enabled)
     {
       free (old_status);
       goto ok_fd;
     }
 
-  if (pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
+  if (open_only == 0
+      && pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
       != PAM_SUCCESS)
     {
       pam_syslog (pamh, LOG_ERR, "error saving old audit status");
@@ -281,13 +276,14 @@ pam_sm_open_session (pam_handle_t *pamh,
       return PAM_SESSION_ERR;
     }
 
-  new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
   if (nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, &new_status,
 	       sizeof (new_status)) != 0
       || nl_recv_ack (fd) != 0)
     {
       pam_syslog (pamh, LOG_ERR, "error setting current audit status: %m");
       close (fd);
+      if (open_only != 0)
+	free (old_status);
       return PAM_SESSION_ERR;
     }
   /* Fall through */
@@ -295,6 +291,8 @@ pam_sm_open_session (pam_handle_t *pamh,
   close (fd);
   pam_syslog (pamh, LOG_DEBUG, "changed status from %d to %d",
 	      old_status->enabled, new_status.enabled);
+  if (open_only != 0)
+    free (old_status);
   return PAM_SUCCESS;
 }
 

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

--- NEW FILE pam-0.99.8.1-unix-hpux-aging.patch ---
diff -up Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h.unix-hpux-aging Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h
--- Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h.unix-hpux-aging	2008-01-08 14:43:36.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h	2008-01-08 15:49:43.000000000 +0100
@@ -13,7 +13,7 @@
 #define OLD_PASSWORDS_FILE      "/etc/security/opasswd"
 
 int
-verify_pwd_hash(const char *p, const char *hash, unsigned int nullok);
+verify_pwd_hash(const char *p, char *hash, unsigned int nullok);
 
 int
 is_pwd_shadowed(const struct passwd *pwd);
diff -up Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c.unix-hpux-aging Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c
--- Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c.unix-hpux-aging	2008-01-08 14:43:36.000000000 +0100
+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c	2008-01-08 15:49:02.000000000 +0100
@@ -44,14 +44,32 @@
 # include "./lckpwdf.-c"
 #endif
 
+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
-verify_pwd_hash(const char *p, const char *hash, unsigned int nullok)
+verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
 {
-	size_t hash_len = strlen(hash);
+	size_t hash_len;
 	char *pp = NULL;
 	int retval;
 	D(("called"));
 
+	strip_hpux_aging(hash);
+	hash_len = strlen(hash);
 	if (!hash_len) {
 		/* the stored password is NULL */
 		if (nullok) { /* this means we've succeeded */

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

View full diff with command:
/usr/bin/cvs -f diff  -kk -u -N -r 1.2 -r 1.3 pam-0.99.8.1-unix-update-helper.patch
Index: pam-0.99.8.1-unix-update-helper.patch
===================================================================
RCS file: /cvs/pkgs/rpms/pam/F-8/pam-0.99.8.1-unix-update-helper.patch,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- pam-0.99.8.1-unix-update-helper.patch	18 Sep 2007 20:23:57 -0000	1.2
+++ pam-0.99.8.1-unix-update-helper.patch	31 Jan 2008 16:14:55 -0000	1.3
@@ -1,14 +1,51 @@
+diff -up Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_sess.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_sess.c
+--- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_sess.c.update-helper	2006-06-17 18:44:58.000000000 +0200
++++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_sess.c	2008-01-07 16:39:07.000000000 +0100
+@@ -73,7 +73,7 @@ PAM_EXTERN int pam_sm_open_session(pam_h
+ 
+ 	D(("called."));
+ 
+-	ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
++	ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
+ 
+ 	retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
+ 	if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
+@@ -107,7 +107,7 @@ PAM_EXTERN int pam_sm_close_session(pam_
+ 
+ 	D(("called."));
+ 
+-	ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
++	ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
+ 
+ 	retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
+ 	if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
 diff -up Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c
 --- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c.update-helper	2007-04-30 12:47:30.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c	2007-09-18 09:52:43.000000000 +0200
++++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c	2008-01-08 16:17:32.000000000 +0100
 @@ -2,6 +2,7 @@
   * 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.
++ * Copyright (c) Red Hat, Inc., 2007, 2008.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
+@@ -63,7 +64,6 @@
+ #ifdef WITH_SELINUX
+ static int selinux_enabled=-1;
+ #include <selinux/selinux.h>
+-static security_context_t prev_context=NULL;
+ #define SELINUX_ENABLED (selinux_enabled!=-1 ? selinux_enabled : (selinux_enabled=is_selinux_enabled()>0))
+ #endif
+ 
+@@ -84,6 +84,7 @@ static security_context_t prev_context=N
+ #include "yppasswd.h"
+ #include "md5.h"
+ #include "support.h"
++#include "passverify.h"
+ #include "bigcrypt.h"
+ 
+ #if !((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
 @@ -92,15 +93,6 @@ extern int getrpcport(const char *host, 
  #endif				/* GNU libc 2.1 */
  
@@ -159,64 +196,7 @@
  	  retval = PAM_AUTH_ERR;
  	} else {
  	  retval = WEXITSTATUS(retval);
-@@ -315,8 +249,56 @@ static int _unix_run_shadow_binary(pam_h
- 
-     return retval;
- }
-+
-+static int selinux_confined(void)
-+{
-+    static int confined = -1;
-+    int fd;
-+    char tempfile[]="/etc/.pwdXXXXXX";
-+
-+    if (confined != -1)
-+    	return confined;
-+
-+    /* cannot be confined without SELinux enabled */
-+    if (!SELINUX_ENABLED){
-+       	confined = 0;
-+       	return confined;
-+    }
-+    
-+    /* let's try opening shadow read only */
-+    if ((fd=open("/etc/shadow", O_RDONLY)) != -1) {
-+        close(fd);
-+        confined = 0;
-+        return confined;
-+    }
-+
-+    if (errno == EACCES) {
-+	confined = 1;
-+	return confined;
-+    }
-+    
-+    /* shadow opening failed because of other reasons let's try 
-+       creating a file in /etc */
-+    if ((fd=mkstemp(tempfile)) != -1) {
-+        unlink(tempfile);
-+        close(fd);
-+        confined = 0;
-+        return confined;
-+    }
-+    
-+    confined = 1;
-+    return confined;
-+}
-+
-+#else
-+static int selinux_confined(void)
-+{
-+    return 0;
-+}
- #endif
- 
-+#include "passupdate.c"
-+
- static int check_old_password(const char *forwho, const char *newpass)
- {
- 	static char buf[16384];
-@@ -354,393 +336,6 @@ static int check_old_password(const char
+@@ -354,393 +288,6 @@ static int check_old_password(const char
  	return retval;
  }
  
@@ -610,18 +590,22 @@
  static int _do_setpass(pam_handle_t* pamh, const char *forwho,
  		       const char *fromwhat,
  		       char *towhat, unsigned int ctrl, int remember)
-@@ -769,7 +364,7 @@ static int _do_setpass(pam_handle_t* pam
+@@ -768,9 +315,7 @@ static int _do_setpass(pam_handle_t* pam
+ 		enum clnt_stat err;
  
  		/* Unlock passwd file to avoid deadlock */
- #ifdef USE_LCKPWDF
+-#ifdef USE_LCKPWDF
 -		ulckpwdf();
+-#endif
 +		unlock_pwdf();
- #endif
  		unlocked = 1;
  
-@@ -832,33 +427,22 @@ static int _do_setpass(pam_handle_t* pam
+ 		/* Initialize password information */
+@@ -830,129 +375,63 @@ static int _do_setpass(pam_handle_t* pam
+ 	}
+ 
  	if (_unix_comesfromsource(pamh, forwho, 1, 0)) {
- #ifdef USE_LCKPWDF
+-#ifdef USE_LCKPWDF
  		if(unlocked) {
 -			int i = 0;
 -			/* These values for the number of attempts and the sleep time
@@ -639,72 +623,169 @@
  				return PAM_AUTHTOK_LOCK_BUSY;
  			}
  		}
- #endif
 +#ifdef WITH_SELINUX
-+	        if (selinux_confined())
++	        if (unix_selinux_confined())
 +			  return _unix_run_update_binary(pamh, ctrl, forwho, fromwhat, towhat, remember);
-+#endif
+ #endif
  		/* first, save old password */
 -		if (save_old_password(pamh, forwho, fromwhat, remember)) {
 +		if (save_old_password(forwho, fromwhat, remember)) {
  			retval = PAM_AUTHTOK_ERR;
  			goto done;
  		}
- 		if (on(UNIX_SHADOW, ctrl) || _unix_shadowed(pwd)) {
- 			retval = _update_shadow(pamh, forwho, towhat);
+-		if (on(UNIX_SHADOW, ctrl) || _unix_shadowed(pwd)) {
+-			retval = _update_shadow(pamh, forwho, towhat);
 -#ifdef WITH_SELINUX
 - 		        if (retval != PAM_SUCCESS && SELINUX_ENABLED)
 -			  retval = _unix_run_shadow_binary(pamh, ctrl, forwho, fromwhat, towhat);
 -#endif
++		if (on(UNIX_SHADOW, ctrl) || is_pwd_shadowed(pwd)) {
++			retval = unix_update_shadow(pamh, forwho, towhat);
  			if (retval == PAM_SUCCESS)
- 				if (!_unix_shadowed(pwd))
- 					retval = _update_passwd(pamh, forwho, "x");
-@@ -870,7 +454,7 @@ static int _do_setpass(pam_handle_t* pam
+-				if (!_unix_shadowed(pwd))
+-					retval = _update_passwd(pamh, forwho, "x");
++				if (!is_pwd_shadowed(pwd))
++					retval = unix_update_passwd(pamh, forwho, "x");
+ 		} else {
+-			retval = _update_passwd(pamh, forwho, towhat);
++			retval = unix_update_passwd(pamh, forwho, towhat);
+ 		}
+ 	}
+ 
  
  done:
- #ifdef USE_LCKPWDF
[...2856 lines suppressed...]
+-			if (pwd == NULL)
+-				retval = PAM_USER_UNKNOWN;
+-			else
+-				retval = PAM_AUTHINFO_UNAVAIL;
+ 			if (on(UNIX_AUDIT, ctrl)) {
+ 				/* this might be a typo and the user has given a password
+ 				   instead of a username. Careful with this. */
+-				pam_syslog(pamh, LOG_ALERT,
++				pam_syslog(pamh, LOG_WARNING,
+ 				         "check pass; user (%s) unknown", name);
+ 			} else {
+ 				name = NULL;
+ 				if (on(UNIX_DEBUG, ctrl) || pwd == NULL) {
+-				    pam_syslog(pamh, LOG_ALERT,
++				    pam_syslog(pamh, LOG_WARNING,
+ 				            "check pass; user unknown");
+ 				} else {
+ 				    /* don't log failure as another pam module can succeed */
+@@ -679,48 +604,7 @@ int _unix_verify_password(pam_handle_t *
+ 			}
+ 		}
+ 	} else {
+-	    size_t salt_len = strlen(salt);
+-	    if (!salt_len) {
+-		/* the stored password is NULL */
+-		if (off(UNIX__NONULL, ctrl)) {/* this means we've succeeded */
+-		    D(("user has empty password - access granted"));
+-		    retval = PAM_SUCCESS;
+-		} else {
+-		    D(("user has empty password - access denied"));
+-		    retval = PAM_AUTH_ERR;
+-		}
+-	    } else if (!p || *salt == '*' || *salt == '!') {
+-		retval = PAM_AUTH_ERR;
+-	    } else {
+-		if (!strncmp(salt, "$1$", 3)) {
+-		    pp = Goodcrypt_md5(p, salt);
+-		    if (pp && strcmp(pp, salt) != 0) {
+-			_pam_delete(pp);
+-			pp = Brokencrypt_md5(p, salt);
+-		    }
+-		} else if (*salt != '$' && salt_len >= 13) {
+-		    pp = bigcrypt(p, salt);
+-		    if (pp && salt_len == 13 && strlen(pp) > salt_len) {
+-			_pam_overwrite(pp + salt_len);
+-		    }
+-		} else {
+-                    /*
+-		     * Ok, we don't know the crypt algorithm, but maybe
+-		     * libcrypt nows about it? We should try it.
+-		     */
+-		    pp = x_strdup (crypt(p, salt));
+-		}
+-		p = NULL;		/* no longer needed here */
+-
+-		/* the moment of truth -- do we agree with the password? */
+-		D(("comparing state of pp[%s] and salt[%s]", pp, salt));
+-
+-		if (pp && strcmp(pp, salt) == 0) {
+-		    retval = PAM_SUCCESS;
+-		} else {
+-		    retval = PAM_AUTH_ERR;
+-		}
+-	    }
++		retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl));
+ 	}
  
- CLEANFILES = *~
+ 	if (retval == PAM_SUCCESS) {
+@@ -809,8 +693,6 @@ cleanup:
+ 		_pam_delete(data_name);
+ 	if (salt)
+ 		_pam_delete(salt);
+-	if (pp)
+-		_pam_delete(pp);
  
--EXTRA_DIST = README md5.c md5_crypt.c lckpwdf.-c $(MANS) CHANGELOG \
-+EXTRA_DIST = README md5.c md5_crypt.c lckpwdf.-c passupdate.c $(MANS) CHANGELOG \
- 		tst-pam_unix $(XMLS) 
+ 	D(("done [%d].", retval));
+ 
+@@ -971,26 +853,12 @@ int _unix_read_password(pam_handle_t * p
+ 	return PAM_SUCCESS;
+ }
  
- man_MANS = pam_unix.8 unix_chkpwd.8
-@@ -16,7 +16,8 @@ securelibdir = $(SECUREDIR)
+-int _unix_shadowed(const struct passwd *pwd)
+-{
+-	if (pwd != NULL) {
+-		if (strcmp(pwd->pw_passwd, "x") == 0) {
+-			return 1;
+-		}
+-		if ((pwd->pw_passwd[0] == '#') &&
+-		    (pwd->pw_passwd[1] == '#') &&
+-		    (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)) {
+-			return 1;
+-		}
+-	}
+-	return 0;
+-}
+-
+ /* ****************************************************************** *
+  * Copyright (c) Jan Rêkorajski 1999.
+  * Copyright (c) Andrew G. Morgan 1996-8.
+  * Copyright (c) Alex O. Yuriev, 1996.
+  * Copyright (c) Cristian Gafton 1996.
++ * 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
+diff -up Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am
+--- Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am.update-helper	2006-12-18 19:50:50.000000000 +0100
++++ Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am	2008-01-08 16:17:32.000000000 +0100
+@@ -16,7 +16,9 @@ securelibdir = $(SECUREDIR)
  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\"
++	-DUPDATE_HELPER=\"$(sbindir)/unix_update\" \
++	-DPATH_RANDOMDEV=\"/dev/urandom\"
  
  if HAVE_LIBSELINUX
    AM_CFLAGS += -D"WITH_SELINUX"
-@@ -34,9 +35,9 @@ endif
+@@ -25,33 +27,40 @@ if HAVE_LIBCRACK
+   AM_CFLAGS += -D"USE_CRACKLIB"
+ endif
+ 
+-pam_unix_la_LDFLAGS = -no-undefined -avoid-version -module \
+-	@LIBCRACK@ @LIBNSL@ -L$(top_builddir)/libpam -lpam \
+-	@LIBCRYPT@ @LIBSELINUX@
++pam_unix_la_LDFLAGS = -no-undefined -avoid-version -module
+ if HAVE_VERSIONING
+   pam_unix_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+ endif
++pam_unix_la_LIBADD = @LIBCRACK@ @LIBNSL@ -L$(top_builddir)/libpam -lpam \
++	@LIBCRYPT@ @LIBSELINUX@
  
  securelib_LTLIBRARIES = pam_unix.la
  
@@ -2588,21 +3681,43 @@
  
  noinst_PROGRAMS = bigcrypt
  
-@@ -48,11 +49,16 @@ bigcrypt_SOURCES = bigcrypt.c bigcrypt_m
+ pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c \
+ 	pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \
+-	yppasswd_xdr.c md5_good.c md5_broken.c
++	passverify.c yppasswd_xdr.c md5_good.c md5_broken.c
+ 
+ bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c
  bigcrypt_CFLAGS = $(AM_CFLAGS)
- bigcrypt_LDFLAGS = @LIBCRYPT@
+-bigcrypt_LDFLAGS = @LIBCRYPT@
++bigcrypt_LDADD = @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@
-+
+-unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
+-unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ -L$(top_builddir)/libpam -lpam \
+-	@LIBCRYPT@ @LIBSELINUX@
++unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \
++	passverify.c
++unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\"
++unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ 
++unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@
++
++unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \
++	passverify.c
++unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\"
++unix_update_LDFLAGS = @PIE_LDFLAGS@ 
++unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@
+ 
  if ENABLE_REGENERATE_MAN
  noinst_DATA = README
- README: pam_unix.8.xml
+diff -up Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_auth.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_auth.c
+--- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_auth.c.update-helper	2006-12-20 15:52:55.000000000 +0100
++++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_auth.c	2008-01-07 16:38:50.000000000 +0100
+@@ -111,7 +111,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_h
+ 
+ 	D(("called."));
+ 
+-	ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
++	ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
+ 
+ 	/* Get a few bytes so we can pass our return value to
+ 	   pam_sm_setcred(). */


Index: pam.spec
===================================================================
RCS file: /cvs/pkgs/rpms/pam/F-8/pam.spec,v
retrieving revision 1.161
retrieving revision 1.162
diff -u -r1.161 -r1.162
--- pam.spec	25 Sep 2007 20:26:29 -0000	1.161
+++ pam.spec	31 Jan 2008 16:14:55 -0000	1.162
@@ -11,7 +11,7 @@
 Summary: A security tool which provides authentication for applications
 Name: pam
 Version: 0.99.8.1
-Release: 10%{?dist}
+Release: 17%{?dist}
 # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant
 # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+,
 # pam_rhosts_auth module is BSD with advertising
@@ -32,8 +32,7 @@
 Patch4:  pam-0.99.8.1-dbpam.patch
 Patch5:  pam-0.99.8.1-audit-no-log.patch
 Patch24: pam-0.99.8.1-unix-update-helper.patch
-Patch25: pam-0.99.7.1-unix-hpux-aging.patch
-Patch26: pam-0.99.8.1-unix-blankpass.patch
+Patch25: pam-0.99.8.1-unix-hpux-aging.patch
 Patch31: pam-0.99.3.0-cracklib-try-first-pass.patch
 Patch32: pam-0.99.3.0-tally-fail-close.patch
 Patch40: pam-0.99.7.1-namespace-temp-logon.patch
@@ -44,11 +43,16 @@
 Patch45: pam-0.99.8.1-selinux-permit.patch
 Patch46: pam-0.99.8.1-succif-in-operator.patch
 Patch47: pam-0.99.8.1-xauth-no-free.patch
+Patch48: pam-0.99.8.1-substack.patch
+Patch49: pam-0.99.8.1-tty-audit.patch
+Patch50: pam-0.99.8.1-tty-audit2.patch
+Patch51: pam-0.99.8.1-audit-failed.patch
+Patch52: pam-0.99.8.1-setkeycreatecon.patch
+Patch53: pam-0.99.8.1-sepermit-kill-user.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires: cracklib, cracklib-dicts >= 2.8
-Requires(pre): grep, coreutils
-Requires(post): mktemp, sed, coreutils, /sbin/ldconfig
+Requires(post): coreutils, /sbin/ldconfig
 BuildRequires: autoconf >= 2.60
 BuildRequires: automake, libtool
 BuildRequires: bison, flex, sed
@@ -71,6 +75,8 @@
 # We internalize libdb to get a non-threaded copy, but we should at least try
 # to coexist with the system's copy of libdb, which will be used to make the
 # files for use by pam_userdb (either by db_load or Perl's DB_File module).
+# The non-threaded db4 is necessary so we do not break single threaded
+# services when they call pam_userdb.so module.
 Conflicts: db4 >= %{db_conflicting_version}
 
 %description
@@ -92,9 +98,6 @@
 
 %prep
 %setup -q -n Linux-PAM-%{version} -a 2 -a 4
-cp %{SOURCE5} .
-cp %{SOURCE6} .
-cp %{SOURCE7} .
 
 %patch1 -p1 -b .redhat-modules
 pushd db-%{db_version}
@@ -104,7 +107,6 @@
 %patch5 -p1 -b .no-log
 %patch24 -p1 -b .update-helper
 %patch25 -p1 -b .unix-hpux-aging
-%patch26 -p1 -b .blankpass
 %patch31 -p1 -b .try-first-pass
 %patch32 -p1 -b .fail-close
 %patch40 -p1 -b .temp-logon
@@ -115,6 +117,12 @@
 %patch45 -p1 -b .permit
 %patch46 -p1 -b .in-operator
 %patch47 -p1 -b .no-free
+%patch48 -p0 -b .substack
+%patch49 -p1 -b .tty-audit
+%patch50 -p1 -b .tty-audit2
+%patch51 -p1 -b .audit-failed
+%patch52 -p1 -b .setkeycreatecon
+%patch53 -p1 -b .kill-user
 
 autoreconf
 
@@ -156,6 +164,7 @@
 	--enable-isadir=../../%{_lib}/security \
 	--with-db-uniquename=_pam
 make
+# we do not use _smp_mflags because the build of sources in yacc/flex fails
 
 %install
 rm -rf $RPM_BUILD_ROOT
@@ -175,20 +184,42 @@
 
 # Install default configuration files.
 install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/pam.d
-install -m 644 other.pamd $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/other
-install -m 644 system-auth.pamd $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/system-auth
-install -m 644 config-util.pamd $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/config-util
+install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/other
+install -m 644 %{SOURCE6} $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/system-auth
+install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/config-util
 install -m 600 /dev/null $RPM_BUILD_ROOT%{_sysconfdir}/security/opasswd
 install -d -m 755 $RPM_BUILD_ROOT/var/log
 install -m 600 /dev/null $RPM_BUILD_ROOT/var/log/faillog
 install -m 600 /dev/null $RPM_BUILD_ROOT/var/log/tallylog
 
-# Forcibly strip binaries.
-strip $RPM_BUILD_ROOT%{_sbindir}/* ||:
-
 # Install man pages.
 install -m 644 %{SOURCE9} %{SOURCE10} $RPM_BUILD_ROOT%{_mandir}/man5/
 
+for phase in auth acct passwd session ; do
+	ln -sf pam_unix.so $RPM_BUILD_ROOT/%{_lib}/security/pam_unix_${phase}.so 
+done
+
+# Remove .la files and make new .so links -- this depends on the value
+# of _libdir not changing, and *not* being /usr/lib.
+install -d -m 755 $RPM_BUILD_ROOT%{_libdir}
+for lib in libpam libpamc libpam_misc ; do
+pushd $RPM_BUILD_ROOT%{_libdir}
+ln -sf ../../%{_lib}/${lib}.so.*.* ${lib}.so
+popd
+rm -f $RPM_BUILD_ROOT/%{_lib}/${lib}.so
+rm -f $RPM_BUILD_ROOT/%{_lib}/${lib}.la
+done
+rm -f $RPM_BUILD_ROOT/%{_lib}/security/*.la
+
+# Duplicate doc file sets.
+rm -fr $RPM_BUILD_ROOT/usr/share/doc/pam
+
+# Create /lib/security in case it isn't the same as /%{_lib}/security.
+install -m755 -d $RPM_BUILD_ROOT/lib/security
+
+%find_lang Linux-PAM
+
+%check
 # Make sure every module subdirectory gave us a module.  Yes, this is hackish.
 for dir in modules/pam_* ; do
 if [ -d ${dir} ] ; then
@@ -204,7 +235,7 @@
 /sbin/ldconfig -n $RPM_BUILD_ROOT/%{_lib}
 for module in $RPM_BUILD_ROOT/%{_lib}/security/pam*.so ; do
 	if ! env LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_lib} \
-		 $RPM_SOURCE_DIR/dlopen.sh -ldl -lpam -L$RPM_BUILD_ROOT/%{_lib} ${module} ; then
+		 %{SOURCE8} -ldl -lpam -L$RPM_BUILD_ROOT/%{_libdir} ${module} ; then
 		echo ERROR module: ${module} cannot be loaded.
 		exit 1
 	fi
@@ -212,84 +243,17 @@
 # libraries, which if loaded in a non-threaded application, can cause Very
 # Bad Things to happen.
 	if env LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_lib} \
-	       LD_PRELOAD=$RPM_BUILD_ROOT/%{_lib}/libpam.so ldd -r ${module} | fgrep -q libpthread ; then
+	       LD_PRELOAD=$RPM_BUILD_ROOT%{_libdir}/libpam.so ldd -r ${module} | fgrep -q libpthread ; then
 		echo ERROR module: ${module} pulls threading libraries.
 		exit 1
 	fi
 done
 
-for phase in auth acct passwd session ; do
-	ln -sf pam_unix.so $RPM_BUILD_ROOT/%{_lib}/security/pam_unix_${phase}.so 
-done
-
-# Remove .la files and make new .so links -- this depends on the value
-# of _libdir not changing, and *not* being /usr/lib.
-install -d -m 755 $RPM_BUILD_ROOT%{_libdir}
-for lib in libpam libpamc libpam_misc ; do
-pushd $RPM_BUILD_ROOT%{_libdir}
-ln -sf ../../%{_lib}/${lib}.so.*.* ${lib}.so
-popd
-rm -f $RPM_BUILD_ROOT/%{_lib}/${lib}.so
-rm -f $RPM_BUILD_ROOT/%{_lib}/${lib}.la
-done
-rm -f $RPM_BUILD_ROOT/%{_lib}/security/*.la
-
-# Duplicate doc file sets.
-rm -fr $RPM_BUILD_ROOT/usr/share/doc/pam
-
-# Create /lib/security in case it isn't the same as /%{_lib}/security.
-install -m755 -d $RPM_BUILD_ROOT/lib/security
-
-%find_lang Linux-PAM
-
 %clean
 rm -rf $RPM_BUILD_ROOT
 
-%pre
-# Figure whether or not we're using shadow/md5 passwords if we're upgrading.
-if [ -f %{_sysconfdir}/pam.d/other ] ; then
-	USEMD5=
-	if [ -f /etc/sysconfig/authconfig ] ; then
-		. /etc/sysconfig/authconfig
-	fi
-	if [ -z "$USEMD5" ] ; then
-		if [ -f /etc/shadow ] ; then
-			passwdfiles="/etc/passwd /etc/shadow"
-		else
-			passwdfiles="/etc/passwd"
-		fi
-		if cut -f2 -d: $passwdfiles | grep -q '^\$1\$' ; then
-			echo USEMD5=yes >> /etc/sysconfig/authconfig
-			USEMD5=yes
-		else
-			echo USEMD5=no  >> /etc/sysconfig/authconfig
-			USEMD5=no
-		fi
-	fi
-fi
-exit 0
-
 %post
 /sbin/ldconfig
-if [ ! -f /etc/shadow ] ; then
-	tmp=`mktemp /etc/pam.d/pam-post.XXXXXX`
-	if [ -n "$tmp" ] ; then
-		sed 's| shadow||g' /etc/pam.d/system-auth > $tmp && \
-		cat $tmp > /etc/pam.d/system-auth
-		rm -f $tmp
-	fi
-fi
-if [ -f /etc/sysconfig/authconfig ] ; then
-	. /etc/sysconfig/authconfig
-fi
-if [ "$USEMD5" = "no" ] ; then
-	tmp=`mktemp /etc/pam.d/pam-post.XXXXXX`
-	if [ -n "$tmp" ] ; then
-		sed 's| md5||g' /etc/pam.d/system-auth > $tmp && \
-		cat $tmp > /etc/pam.d/system-auth
-		rm -f $tmp
-	fi
-fi
 if [ ! -a /var/log/faillog ] ; then
 	install -m 600 /dev/null /var/log/faillog
 fi
@@ -363,6 +327,7 @@
 /%{_lib}/security/pam_tally2.so
 /%{_lib}/security/pam_time.so
 /%{_lib}/security/pam_timestamp.so
+/%{_lib}/security/pam_tty_audit.so
 /%{_lib}/security/pam_umask.so
 /%{_lib}/security/pam_unix.so
 /%{_lib}/security/pam_unix_acct.so
@@ -391,6 +356,7 @@
 %dir %{_sysconfdir}/security/console.perms.d
 %config %{_sysconfdir}/security/console.perms.d/50-default.perms
 %dir /var/run/console
+%dir /var/run/sepermit
 %ghost %verify(not md5 size mtime) /var/log/faillog
 %ghost %verify(not md5 size mtime) /var/log/tallylog
 %{_mandir}/man5/*
@@ -407,6 +373,31 @@
 %doc doc/adg/*.txt doc/adg/html
 
 %changelog
+* Mon Jan 28 2008 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-17
+- test for setkeycreatecon correctly
+- add exclusive login mode of operation to pam_selinux_permit (original
+  patch by Dan Walsh)
+
+* Tue Jan 22 2008 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-16
+- add auditing to pam_access, pam_limits, and pam_time
+- moved sanity testing code to check script
+
+* Mon Jan 14 2008 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-15
+- merge review fixes (#226228)
+
+* Wed Jan  8 2008 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-14
+- support for sha256 and sha512 password hashes
+- account expiry checks moved to unix_chkpwd helper
+
+* Wed Jan  2 2008 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-13
+- wildcard match support in pam_tty_audit (by Miloslav Trmač)
+
+* Thu Nov 29 2007 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-12
+- add pam_tty_audit module (#244352) - written by Miloslav Trmač
+
+* Wed Nov  7 2007 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-11
+- add substack support
+
 * Tue Sep 25 2007 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-10
 - update db4 to 4.6.19 (#274661)
 


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


--- pam-0.99.8.1-unix-blankpass.patch DELETED ---




More information about the fedora-extras-commits mailing list