Submitted By: DJ Lucas (dj AT linuxfromscratch DOT org)
Date: 2005-07-06
Initial Package Version: 4.0.9
Origin: http://lists.pld.org.pl/mailman/pipermail/shadow/2005-June/000125.html
Upstream Status: Accepted
Description: Fixes erroneous warning messages when used with Linux-PAM,
             backported from 4.0.10+ CVS.

$LastChangedBy: bdubbs $
$Date: 2005-08-01 13:29:19 -0600 (Mon, 01 Aug 2005) $


diff -Naur shadow-4.0.9-orig/libmisc/setupenv.c shadow-4.0.9/libmisc/setupenv.c
--- shadow-4.0.9-orig/libmisc/setupenv.c	2005-03-30 23:14:50.000000000 -0600
+++ shadow-4.0.9/libmisc/setupenv.c	2005-07-06 20:52:18.000000000 -0500
@@ -238,7 +238,17 @@
 	 * Create the PATH environmental variable and export it.
 	 */
 
+	/*
+	 * Export the user name.  For BSD derived systems, it's "USER", for
+	 * all others it's "LOGNAME".  We set both of them.
+	 */
+
+	addenv ("USER", info->pw_name);
+	addenv ("LOGNAME", info->pw_name);
+
+#ifndef USE_PAM
 	cp = getdef_str ((info->pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH");
+
 	if (!cp) {
 		/* not specified, use a minimal default */
 		addenv ("PATH=/bin:/usr/bin", NULL);
@@ -251,14 +261,6 @@
 	}
 
 	/*
-	 * Export the user name.  For BSD derived systems, it's "USER", for
-	 * all others it's "LOGNAME".  We set both of them.
-	 */
-
-	addenv ("USER", info->pw_name);
-	addenv ("LOGNAME", info->pw_name);
-
-	/*
 	 * MAILDIR environment variable for Qmail
 	 */
 	if ((cp = getdef_str ("QMAIL_DIR")))
@@ -274,6 +276,7 @@
 	else if ((cp = getdef_str ("MAIL_FILE")))
 		addenv_path ("MAIL", info->pw_dir, cp);
 	else {
+
 #if defined(MAIL_SPOOL_FILE)
 		addenv_path ("MAIL", info->pw_dir, MAIL_SPOOL_FILE);
 #elif defined(MAIL_SPOOL_DIR)
@@ -281,11 +284,10 @@
 #endif
 	}
 
-#ifndef USE_PAM
 	/*
 	 * Read environment from optional config file.  --marekm
 	 */
 	if ((envf = getdef_str ("ENVIRON_FILE")))
 		read_env_file (envf);
-#endif
+#endif /* !USE_PAM */
 }
diff -Naur shadow-4.0.9-orig/libmisc/tz.c shadow-4.0.9/libmisc/tz.c
--- shadow-4.0.9-orig/libmisc/tz.c	2003-04-22 05:59:22.000000000 -0500
+++ shadow-4.0.9/libmisc/tz.c	2005-07-06 20:52:18.000000000 -0500
@@ -49,8 +49,10 @@
 
 	if ((fp = fopen (fname, "r")) == NULL ||
 	    fgets (tzbuf, sizeof (tzbuf), fp) == NULL) {
+#ifndef USE_PAM
 		if (!(def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/')
 			def_tz = "TZ=CST6CDT";
+#endif /* !USE_PAM */
 
 		strcpy (tzbuf, def_tz);
 	} else
diff -Naur shadow-4.0.9-orig/src/login.c shadow-4.0.9/src/login.c
--- shadow-4.0.9-orig/src/login.c	2005-04-18 09:10:30.000000000 -0500
+++ shadow-4.0.9/src/login.c	2005-07-06 20:52:18.000000000 -0500
@@ -30,7 +30,7 @@
 #include <config.h>
 
 #include "rcsid.h"
-RCSID (PKG_VER "$Id: login.c,v 1.52 2005/04/17 15:38:56 kloczek Exp $")
+RCSID (PKG_VER "$Id: login.c,v 1.59 2005/06/20 09:36:27 kloczek Exp $")
 #include "prototypes.h"
 #include "defines.h"
 #include <sys/stat.h>
@@ -277,9 +277,11 @@
 
 	if ((tmp = getenv ("TZ"))) {
 		addenv ("TZ", tmp);
-	} else if ((cp = getdef_str ("ENV_TZ")))
+	} 
+#ifndef USE_PAM
+		else if ((cp = getdef_str ("ENV_TZ")))
 		addenv (*cp == '/' ? tz (cp) : cp, NULL);
-
+#endif /* !USE_PAM */
 	/* 
 	 * Add the clock frequency so that profiling commands work
 	 * correctly.
@@ -287,8 +289,11 @@
 
 	if ((tmp = getenv ("HZ"))) {
 		addenv ("HZ", tmp);
-	} else if ((cp = getdef_str ("ENV_HZ")))
+	} 
+#ifndef USE_PAM
+		else if ((cp = getdef_str ("ENV_HZ")))
 		addenv (cp, NULL);
+#endif /* !USE_PAM */
 }
 
 
@@ -347,8 +352,7 @@
 	int retcode;
 	pid_t child;
 	char *pam_user;
-#endif				/* USE_PAM */
-#if defined(SHADOWPWD) && !defined(USE_PAM)
+#else
 	struct spwd *spwd = NULL;
 #endif
 	/*
@@ -369,7 +373,7 @@
 
 	check_flags (argc, argv);
 
-	while ((flag = getopt (argc, argv, "d:f:h:pr:")) != EOF) {
+	while ((flag = getopt (argc, argv, "d:f::h:pr:")) != EOF) {
 		switch (flag) {
 		case 'p':
 			pflg++;
@@ -378,11 +382,16 @@
 			/*
 			 * username must be a separate token
 			 * (-f root, *not* -froot).  --marekm
+			 *
+			 * if -f has an arg, use that, else use the
+			 * normal user name passed after all options
+			 * --benc
 			 */
-			if (optarg != argv[optind - 1])
+			if (optarg != NULL && optarg != argv[optind - 1])
 				usage ();
 			fflg++;
-			STRFCPY (username, optarg);
+			if (optarg)
+				STRFCPY (username, optarg);
 			break;
 #ifdef	RLOGIN
 		case 'r':
@@ -418,7 +427,7 @@
 	 */
 
 	if ((rflg || fflg || hflg) && !amroot) {
-		fprintf (stderr, _("%s: permission denied.\n"), Prog);
+		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
 		exit (1);
 	}
 
@@ -498,6 +507,8 @@
 
 		setup_tty ();
 
+#ifndef USE_PAM
+
 		umask (getdef_num ("UMASK", 077));
 
 		{
@@ -514,6 +525,8 @@
 				set_filesize_limit (limit);
 		}
 
+#endif /* !USE_PAM */
+
 		/*
 		 * The entire environment will be preserved if the -p flag
 		 * is used.
@@ -535,7 +548,7 @@
 		init_env ();
 
 		if (optind < argc) {	/* get the user name */
-			if (rflg || fflg)
+			if (rflg || (fflg && username[0]))
 				usage ();
 
 			STRFCPY (username, argv[optind]);
@@ -703,11 +716,14 @@
 
 		if (!pwd || setup_groups (pwd))
 			exit (1);
+		else
+			pwent = *pwd;
 
 		retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
 		PAM_FAIL_CHECK;
 
-		retcode = pam_open_session (pamh, 0);
+		retcode = pam_open_session (pamh,
+					    hushed (&pwent) ? PAM_SILENT : 0);
 		PAM_FAIL_CHECK;
 
 #else				/* ! USE_PAM */
@@ -742,7 +758,6 @@
 			pwent = *pwd;
 		}
 #ifndef USE_PAM
-#ifdef SHADOWPWD
 		spwd = NULL;
 		if (pwd && strcmp (pwd->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
 			spwd = getspnam (username);
@@ -753,7 +768,6 @@
 					 "no shadow password for `%s'%s",
 					 username, fromhost));
 		}
-#endif				/* SHADOWPWD */
 
 		/*
 		 * If the encrypted password begins with a "!", the account
@@ -918,9 +932,7 @@
 		subroot++;	/* say i was here again */
 		endpwent ();	/* close all of the file which were */
 		endgrent ();	/* open in the original rooted file */
-#ifdef	SHADOWPWD
 		endspent ();	/* system. they will be re-opened */
-#endif
 #ifdef	SHADOWGRP
 		endsgent ();	/* in the new rooted file system */
 #endif
@@ -938,7 +950,6 @@
 	 * and changes to the user in the child before executing the passwd
 	 * program.  --marekm
 	 */
-#ifdef	SHADOWPWD
 	if (spwd) {		/* check for age of password */
 		if (expire (&pwent, spwd)) {
 			pwd = getpwnam (username);
@@ -947,11 +958,44 @@
 				pwent = *pwd;
 		}
 	}
-#endif				/* SHADOWPWD */
 	setup_limits (&pwent);	/* nice, ulimit etc. */
 #endif				/* ! USE_PAM */
 	chown_tty (tty, &pwent);
 
+#ifdef USE_PAM
+	/*
+	 * We must fork before setuid() because we need to call
+	 * pam_close_session() as root.
+	 *
+	 * Note: not true in other (non-Linux) PAM implementations, where
+	 * the parent process of login (init, telnetd, ...) is responsible
+	 * for calling pam_close_session(). This avoids an extra process for
+	 * each login. Maybe we should do this on Linux too? We let the
+	 * admin configure whether they need to keep login around to close
+	 * sessions.
+	 */
+	if (getdef_bool ("CLOSE_SESSIONS")) {
+		signal (SIGINT, SIG_IGN);
+		child = fork ();
+		if (child < 0) {
+			/* error in fork() */
+			fprintf (stderr,
+				 "login: failure forking: %s",
+				 strerror (errno));
+			PAM_END;
+			exit (0);
+		} else if (child) {
+			/*
+			 * parent - wait for child to finish, then cleanup
+			 * session
+			 */
+			wait (NULL);
+			PAM_END;
+			exit (0);
+		}
+		/* child */
+	}
+#endif
 	/* We call set_groups() above because this clobbers pam_groups.so */
 #ifndef USE_PAM
 	if (setup_uid_gid (&pwent, is_console))
@@ -1021,11 +1065,7 @@
 #endif
 			printf (".\n");
 		}
-#ifdef	SHADOWPWD
 		agecheck (&pwent, spwd);
-#else
-		agecheck (&pwent);
-#endif
 
 		mailcheck ();	/* report on the status of mail */
 #endif				/* !USE_PAM */
@@ -1039,55 +1079,22 @@
 	signal (SIGTERM, SIG_DFL);	/* default terminate signal */
 	signal (SIGALRM, SIG_DFL);	/* default alarm signal */
 	signal (SIGHUP, SIG_DFL);	/* added this.  --marekm */
-
-#ifdef USE_PAM
-	/*
-	 * We must fork before setuid() because we need to call
-	 * pam_close_session() as root.
-	 *
-	 * Note: not true in other (non-Linux) PAM implementations, where
-	 * the parent process of login (init, telnetd, ...) is responsible
-	 * for calling pam_close_session(). This avoids an extra process for
-	 * each login. Maybe we should do this on Linux too? We let the
-	 * admin configure whether they need to keep login around to close
-	 * sessions.
-	 */
-	if (getdef_bool ("CLOSE_SESSIONS")) {
-		signal (SIGINT, SIG_IGN);
-		child = fork ();
-		if (child < 0) {
-			/* error in fork() */
-			fprintf (stderr,
-				 "login: failure forking: %s",
-				 strerror (errno));
-			PAM_END;
-			exit (0);
-		} else if (child) {
-			/*
-			 * parent - wait for child to finish, then cleanup
-			 * session
-			 */
-			wait (NULL);
-			PAM_END;
-			exit (0);
-		}
-		/* child */
-	}
-#endif
 	signal (SIGINT, SIG_DFL);	/* default interrupt signal */
 
 	endpwent ();		/* stop access to password file */
 	endgrent ();		/* stop access to group file */
-#ifdef	SHADOWPWD
 	endspent ();		/* stop access to shadow passwd file */
-#endif
 #ifdef	SHADOWGRP
 	endsgent ();		/* stop access to shadow group file */
 #endif
 	if (pwent.pw_uid == 0)
 		SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost));
 	else if (getdef_bool ("LOG_OK_LOGINS"))
+#ifdef USE_PAM
+		SYSLOG ((LOG_INFO, "`%s' logged in %s", pam_user, fromhost));
+#else
 		SYSLOG ((LOG_INFO, "`%s' logged in %s", username, fromhost));
+#endif
 	closelog ();
 	if ((tmp = getdef_str ("FAKE_SHELL")) != NULL) {
 		shell (tmp, pwent.pw_shell);	/* fake shell */
diff -Naur shadow-4.0.9-orig/src/su.c shadow-4.0.9/src/su.c
--- shadow-4.0.9-orig/src/su.c	2005-04-02 08:09:48.000000000 -0600
+++ shadow-4.0.9/src/su.c	2005-07-06 20:52:18.000000000 -0500
@@ -30,17 +30,11 @@
 #include <config.h>
 
 #include "rcsid.h"
-RCSID (PKG_VER "$Id: su.c,v 1.30 2005/04/02 14:09:48 kloczek Exp $")
+RCSID (PKG_VER "$Id: su.c,v 1.34 2005/06/20 10:17:08 kloczek Exp $")
 #include <sys/types.h>
 #include <stdio.h>
 #ifdef USE_PAM
 #include "pam_defs.h"
-static const struct pam_conv conv = {
-	misc_conv,
-	NULL
-};
-
-static pam_handle_t *pamh = NULL;
 #endif
 
 #include "prototypes.h"
@@ -64,8 +58,18 @@
 static char name[BUFSIZ];
 static char oldname[BUFSIZ];
 
-static char *Prog;
+#ifdef USE_PAM
+static const struct pam_conv conv = {
+	misc_conv,
+	NULL
+};
 
+static pam_handle_t *pamh = NULL;
+#endif 
+
+static int caught = 0;
+
+static char *Prog;
 extern struct passwd pwent;
 
 /*
@@ -73,9 +77,8 @@
  */
 
 extern char **newenvp;
-extern size_t newenvc;
-
 extern char **environ;
+extern size_t newenvc;
 
 /* local function prototypes */
 
@@ -125,7 +128,7 @@
 #ifdef USE_SYSLOG
 	if (getdef_bool ("SYSLOG_SU_ENAB"))
 		SYSLOG ((pwent.pw_uid ? LOG_INFO : LOG_NOTICE,
-			 "- %s %s-%s", tty,
+			 "- %s %s:%s", tty,
 			 oldname[0] ? oldname : "???", name[0] ? name : "???"));
 	closelog ();
 #endif
@@ -133,9 +136,8 @@
 	exit (1);
 }
 
-#ifdef USE_PAM
-static int caught = 0;
 
+#ifdef USE_PAM
 /* Signal handler for parent process later */
 static void su_catch_sig (int sig)
 {
@@ -270,9 +272,8 @@
 	RETSIGTYPE (*oldsig) ();
 	int is_console = 0;
 
-#ifdef	SHADOWPWD
 	struct spwd *spwd = 0;
-#endif
+
 #ifdef SU_ACCESS
 	char *oldpass;
 #endif
@@ -342,13 +343,6 @@
 	 */
 
 	if (fakelogin) {
-		if ((cp = getdef_str ("ENV_TZ")))
-			addenv (*cp == '/' ? tz (cp) : cp, NULL);
-		/*
-		 * The clock frequency will be reset to the login value if required
-		 */
-		if ((cp = getdef_str ("ENV_HZ")))
-			addenv (cp, NULL);	/* set the default $HZ, if one */
 		/*
 		 * The terminal type will be left alone if it is present in
 		 * the environment already.
@@ -356,6 +350,13 @@
 		if ((cp = getenv ("TERM")))
 			addenv ("TERM", cp);
 #ifndef USE_PAM
+		if ((cp = getdef_str ("ENV_TZ")))
+			addenv (*cp == '/' ? tz (cp) : cp, NULL);
+		/*
+		 * The clock frequency will be reset to the login value if required
+		 */
+		if ((cp = getdef_str ("ENV_HZ")))
+			addenv (cp, NULL);	/* set the default $HZ, if one */
 		/*
 		 * Also leave DISPLAY and XAUTHORITY if present, else
 		 * pam_xauth will not work.
@@ -405,10 +406,8 @@
 	 * Sort out the password of user calling su, in case needed later
 	 * -- chris
 	 */
-#ifdef SHADOWPWD
 	if ((spwd = getspnam (oldname)))
 		pw->pw_passwd = spwd->sp_pwdp;
-#endif
 	oldpass = xstrdup (pw->pw_passwd);
 #endif				/* SU_ACCESS */
 
@@ -449,12 +448,10 @@
 		exit (1);
 	}
 #ifndef USE_PAM
-#ifdef SHADOWPWD
 	spwd = NULL;
 	if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0
 	    && (spwd = getspnam (name)))
 		pw->pw_passwd = spwd->sp_pwdp;
-#endif
 #endif				/* !USE_PAM */
 	pwent = *pw;
 
@@ -466,7 +463,7 @@
 
 	/* The original Shadow 3.3.2 did this differently. Do it like BSD:
 	 *
-	 * - check for uid 0 instead of name "root" - there are systems with
+	 * - check for UID 0 instead of name "root" - there are systems with
 	 *   several root accounts under different names,
 	 *
 	 * - check the contents of /etc/group instead of the current group
@@ -563,7 +560,6 @@
 	 */
 
 	if (!amroot) {
-#ifdef	SHADOWPWD
 		if (!spwd)
 			spwd = pwd_to_spwd (&pwent);
 
@@ -572,7 +568,6 @@
 				 "Expired account %s", name));
 			su_failure (tty);
 		}
-#endif
 	}
 
 	/*
@@ -593,6 +588,7 @@
 #endif				/* !USE_PAM */
 
 	signal (SIGINT, SIG_DFL);
+#ifndef USE_PAM
 	cp = getdef_str ((pwent.pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH");
 
 	/* XXX very similar code duplicated in libmisc/setupenv.c */
@@ -604,10 +600,8 @@
 		addenv ("PATH", cp);
 	}
 
-/* setup the environment for pam later on, else we run into auth problems */
-#ifndef USE_PAM
 	environ = newenvp;	/* make new environment active */
-#endif
+#endif /* !USE_PAM */
 
 	if (getenv ("IFS"))	/* don't export user IFS ... */
 		addenv ("IFS= \t\n", NULL);	/* ... instead, set a safe IFS */
@@ -616,20 +610,16 @@
 		pwent.pw_shell++;	/* skip the '*' */
 		subsystem (&pwent);	/* figure out what to execute */
 		endpwent ();
-#ifdef SHADOWPWD
 		endspent ();
-#endif
 		goto top;
 	}
 
 	sulog (tty, 1, oldname, name);	/* save SU information */
 	endpwent ();
-#ifdef SHADOWPWD
 	endspent ();
-#endif
 #ifdef USE_SYSLOG
 	if (getdef_bool ("SYSLOG_SU_ENAB"))
-		SYSLOG ((LOG_INFO, "+ %s %s-%s", tty,
+		SYSLOG ((LOG_INFO, "+ %s %s:%s", tty,
 			 oldname[0] ? oldname : "???", name[0] ? name : "???"));
 #endif
 
diff -Naur shadow-4.0.9-orig/src/sulogin.c shadow-4.0.9/src/sulogin.c
--- shadow-4.0.9-orig/src/sulogin.c	2005-03-30 23:14:54.000000000 -0600
+++ shadow-4.0.9/src/sulogin.c	2005-07-06 20:52:18.000000000 -0500
@@ -140,10 +140,14 @@
 	while (*envp)		/* add inherited environment, */
 		addenv (*envp++, NULL);	/* some variables change later */
 
+#ifndef USE_PAM
+
 	if ((cp = getdef_str ("ENV_TZ")))
 		addenv (*cp == '/' ? tz (cp) : cp, NULL);
 	if ((cp = getdef_str ("ENV_HZ")))
 		addenv (cp, NULL);	/* set the default $HZ, if one */
+#endif /* !USE_PAM */
+
 	(void) strcpy (name, "root");	/* KLUDGE!!! */
 
 	signal (SIGALRM, catch);	/* exit if the timer expires */
