[Pkg-shadow-commits] r2727 - in upstream/trunk: . src

Nicolas FRANÇOIS nekral-guest at alioth.debian.org
Mon Apr 20 13:29:15 UTC 2009


Author: nekral-guest
Date: 2009-04-20 13:29:15 +0000 (Mon, 20 Apr 2009)
New Revision: 2727

Modified:
   upstream/trunk/ChangeLog
   upstream/trunk/src/login.c
Log:
	* src/login.c: Get rid of pwent. pwd is sufficient as long as it
	is always coming from xgetpwnam. There is no need to copy pwd to
	pwent, this was not a good idea anyway as the strings from pwd
	were not duplicated.
	* src/login.c: Always free the pwd and spwd structure when we
	retrieve a new one. This will clear the password of the previous
	user from the memory.
	* src/login.c: user_passwd is used to keep point to the password
	of the user being authenticated.
	* src/login.c: (non PAM) Fail if the user's entry cannot be found
	after the user updated her password (if expire() requested an
	update).
	* src/login.c: If the user does not exist on the system, there is
	no need to build a pwd structure (with shell).


Modified: upstream/trunk/ChangeLog
===================================================================
--- upstream/trunk/ChangeLog	2009-04-20 13:12:09 UTC (rev 2726)
+++ upstream/trunk/ChangeLog	2009-04-20 13:29:15 UTC (rev 2727)
@@ -1,5 +1,22 @@
 2009-04-20  Nicolas François  <nicolas.francois at centraliens.net>
 
+	* src/login.c: Get rid of pwent. pwd is sufficient as long as it
+	is always coming from xgetpwnam. There is no need to copy pwd to
+	pwent, this was not a good idea anyway as the strings from pwd
+	were not duplicated.
+	* src/login.c: Always free the pwd and spwd structure when we
+	retrieve a new one. This will clear the password of the previous
+	user from the memory.
+	* src/login.c: user_passwd is used to keep point to the password
+	of the user being authenticated.
+	* src/login.c: (non PAM) Fail if the user's entry cannot be found
+	after the user updated her password (if expire() requested an
+	update).
+	* src/login.c: If the user does not exist on the system, there is
+	no need to build a pwd structure (with shell).
+
+2009-04-20  Nicolas François  <nicolas.francois at centraliens.net>
+
 	* src/login.c: ttytype already checks for TTYTYPE_FILE and TERM.
 	Just call ttytype.
 

Modified: upstream/trunk/src/login.c
===================================================================
--- upstream/trunk/src/login.c	2009-04-20 13:12:09 UTC (rev 2726)
+++ upstream/trunk/src/login.c	2009-04-20 13:29:15 UTC (rev 2727)
@@ -85,8 +85,6 @@
 static char *username = NULL;
 static int reason = PW_LOGIN;
 
-static struct passwd pwent;
-
 #if HAVE_UTMPX_H
 extern struct utmpx utxent;
 struct utmpx failent;
@@ -490,10 +488,9 @@
 	const char *cp;
 	char *tmp;
 	char fromhost[512];
-	struct passwd *pwd;
+	struct passwd *pwd = NULL;
 	char **envp = environ;
 #ifndef USE_PAM
-	static char temp_pw[2];
 	static char temp_shell[] = "/bin/sh";
 #endif
 	const char *failent_user;
@@ -881,8 +878,6 @@
 		exit (1);
 	}
 
-	pwent = *pwd;
-
 	retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
 	PAM_FAIL_CHECK;
 	/* NOTE: If pam_setcred changes PAM_USER, this will not be taken
@@ -891,6 +886,22 @@
 
 #else				/* ! USE_PAM */
 	while (true) {	/* repeatedly get login/password pairs */
+		/* user_passwd is always a pointer to this constant string
+		 * or a passwd or shadow password that will be memzero by
+		 * passwd_free / shadow_free.
+		 * Do not free() user_passwd. */
+		const char *user_passwd = "!";
+
+		/* Do some cleanup to avoid keeping entries we do not need
+		 * anymore. */
+		if (NULL != pwd) {
+			passwd_free (pwd);
+		}
+		if (NULL != spwd) {
+			shadow_free (spwd);
+			spwd = NULL;
+		}
+
 		failed = false;	/* haven't failed authentication yet */
 		if (NULL == username) {	/* need to get a login id */
 			if (subroot) {
@@ -913,25 +924,31 @@
 
 		pwd = xgetpwnam (username);
 		if (NULL == pwd) {
-			pwent.pw_name = username;
-			strcpy (temp_pw, "!");
-			pwent.pw_passwd = temp_pw;
-			pwent.pw_shell = temp_shell;
-
 			preauth_flag = false;
 			failed = true;
 		} else {
-			pwent = *pwd;
+			user_passwd = pwd->pw_passwd;
+			/*
+			 * If the encrypted password begins with a "!",
+			 * the account is locked and the user cannot
+			 * login, even if they have been
+			 * "pre-authenticated."
+			 */
+			if (   ('!' == user_passwd[0])
+			    || ('*' == user_passwd[0])) {
+				failed = true;
+			}
 		}
 
-		spwd = NULL;
-		if (   (NULL != pwd)
-		    && (strcmp (pwd->pw_passwd, SHADOW_PASSWD_STRING) == 0)) {
-			/* !USE_PAM, no need for xgetspnam */
-			spwd = getspnam (username);
+		if (strcmp (user_passwd, SHADOW_PASSWD_STRING) == 0) {
+			spwd = xgetspnam (username);
 			if (NULL != spwd) {
-				pwent.pw_passwd = spwd->sp_pwdp;
+				user_passwd = spwd->sp_pwdp;
 			} else {
+				/* The user exists in passwd, but not in
+				 * shadow. SHADOW_PASSWD_STRING indicates
+				 * that the password shall be in shadow.
+				 */
 				SYSLOG ((LOG_WARN,
 				         "no shadow password for '%s'%s",
 				         username, fromhost));
@@ -939,16 +956,6 @@
 		}
 
 		/*
-		 * If the encrypted password begins with a "!", the account
-		 * is locked and the user cannot login, even if they have
-		 * been "pre-authenticated."
-		 */
-		if (   ('!' == pwent.pw_passwd[0])
-		    || ('*' == pwent.pw_passwd[0])) {
-			failed = true;
-		}
-
-		/*
 		 * The -r and -f flags provide a name which has already
 		 * been authenticated by some server.
 		 */
@@ -956,8 +963,7 @@
 			goto auth_ok;
 		}
 
-		if (pw_auth (pwent.pw_passwd, username,
-		             reason, (char *) 0) == 0) {
+		if (pw_auth (user_passwd, username, reason, (char *) 0) == 0) {
 			goto auth_ok;
 		}
 
@@ -972,8 +978,8 @@
 		 * authenticated and so on.
 		 */
 		if (   !failed
-		    && (NULL != pwent.pw_name)
-		    && (0 == pwent.pw_uid)
+		    && (NULL != pwd)
+		    && (0 == pwd->pw_uid)
 		    && !is_console) {
 			SYSLOG ((LOG_CRIT, "ILLEGAL ROOT LOGIN %s", fromhost));
 			failed = true;
@@ -986,7 +992,7 @@
 		}
 		if (   (NULL != pwd)
 		    && getdef_bool ("FAILLOG_ENAB")
-		    && !failcheck (pwent.pw_uid, &faillog, failed)) {
+		    && !failcheck (pwd->pw_uid, &faillog, failed)) {
 			SYSLOG ((LOG_CRIT,
 			         "exceeded failure limit for '%s' %s",
 			         username, fromhost));
@@ -998,7 +1004,7 @@
 
 		/* don't log non-existent users */
 		if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
-			failure (pwent.pw_uid, tty, &faillog);
+			failure (pwd->pw_uid, tty, &faillog);
 		}
 		if (getdef_str ("FTMP_FILE") != NULL) {
 #if HAVE_UTMPX_H
@@ -1036,7 +1042,7 @@
 		 * guys won't see that the passwordless account exists at
 		 * all).  --marekm
 		 */
-		if (pwent.pw_passwd[0] == '\0') {
+		if (user_passwd[0] == '\0') {
 			pw_auth ("!", username, reason, (char *) 0);
 		}
 
@@ -1075,7 +1081,7 @@
 	 * by Ivan Nejgebauer <ian at unsux.ns.ac.yu>.  --marekm
 	 */
 	if (   getdef_bool ("PORTTIME_CHECKS_ENAB")
-	    && !isttytime (pwent.pw_name, tty, time ((time_t *) 0))) {
+	    && !isttytime (username, tty, time ((time_t *) 0))) {
 		SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
 		         username, fromhost));
 		closelog ();
@@ -1083,7 +1089,7 @@
 		exit (1);
 	}
 
-	check_nologin (pwent.pw_uid == 0);
+	check_nologin (pwd->pw_uid == 0);
 #endif
 
 	if (getenv ("IFS")) {	/* don't export user IFS ... */
@@ -1091,9 +1097,9 @@
 	}
 
 	setutmp (username, tty, hostname);	/* make entry in utmp & wtmp files */
-	if (pwent.pw_shell[0] == '*') {	/* subsystem root */
-		pwent.pw_shell++;	/* skip the '*' */
-		subsystem (&pwent);	/* figure out what to execute */
+	if (pwd->pw_shell[0] == '*') {	/* subsystem root */
+		pwd->pw_shell++;	/* skip the '*' */
+		subsystem (pwd);	/* figure out what to execute */
 		subroot = true;	/* say I was here again */
 		endpwent ();	/* close all of the file which were */
 		endgrent ();	/* open in the original rooted file */
@@ -1110,7 +1116,7 @@
 	                        AUDIT_USER_LOGIN,
 	                        NULL,    /* Prog. name */
 	                        "login",
-	                        pwd->pw_name,
+	                        username,
 	                        AUDIT_NO_ID,
 	                        hostname,
 	                        NULL,    /* addr */
@@ -1121,31 +1127,38 @@
 
 #ifndef USE_PAM			/* pam_lastlog handles this */
 	if (getdef_bool ("LASTLOG_ENAB")) {	/* give last login and log this one */
-		dolastlog (&lastlog, &pwent, tty, hostname);
+		dolastlog (&lastlog, pwd, tty, hostname);
 	}
 #endif
 
 #ifndef USE_PAM			/* PAM handles this as well */
 	/*
 	 * Have to do this while we still have root privileges, otherwise we
-	 * don't have access to /etc/shadow. expire() closes password files,
-	 * and changes to the user in the child before executing the passwd
-	 * program.  --marekm
+	 * don't have access to /etc/shadow.
 	 */
-	if (spwd) {		/* check for age of password */
-		if (expire (&pwent, spwd)) {
-			/* !USE_PAM, no need for xgetpwnam */
-			pwd = getpwnam (username);
-			/* !USE_PAM, no need for xgetspnam */
-			spwd = getspnam (username);
-			if (pwd) {
-				pwent = *pwd;
+	if (NULL != spwd) {		/* check for age of password */
+		if (expire (pwd, spwd)) {
+			/* The user updated her password, get the new
+			 * entries.
+			 * Use the x variants because we need to keep the
+			 * entry for a long time, and there might be other
+			 * getxxyy in between.
+			 */
+			passwd_free (pwd);
+			pwd = xgetpwnam (username);
+			if (NULL == pwd) {
+				SYSLOG ((LOG_ERR,
+				         "cannot find user %s after update of expired password",
+				         username));
+				exit (1);
 			}
+			shadow_free (spwd);
+			spwd = xgetspnam (username);
 		}
 	}
-	setup_limits (&pwent);	/* nice, ulimit etc. */
+	setup_limits (pwd);	/* nice, ulimit etc. */
 #endif				/* ! USE_PAM */
-	chown_tty (&pwent);
+	chown_tty (pwd);
 
 #ifdef USE_PAM
 	/*
@@ -1180,7 +1193,8 @@
 	}
 
 
-	/*
+	/* The pwd and spwd entries for the user have been copied.
+	 *
 	 * Close all the files so that unauthorized access won't occur.
 	 */
 	endpwent ();		/* stop access to password file */
@@ -1192,18 +1206,18 @@
 
 	/* Drop root privileges */
 #ifndef USE_PAM
-	if (setup_uid_gid (&pwent, is_console))
+	if (setup_uid_gid (pwd, is_console))
 #else
 	/* The group privileges were already dropped.
 	 * See setup_groups() above.
 	 */
-	if (change_uid (&pwent))
+	if (change_uid (pwd))
 #endif
 	{
 		exit (1);
 	}
 
-	setup_env (&pwent);	/* set env vars, cd to the home dir */
+	setup_env (pwd);	/* set env vars, cd to the home dir */
 
 #ifdef USE_PAM
 	{
@@ -1280,7 +1294,7 @@
 	(void) signal (SIGHUP, SIG_DFL);	/* added this.  --marekm */
 	(void) signal (SIGINT, SIG_DFL);	/* default interrupt signal */
 
-	if (0 == pwent.pw_uid) {
+	if (0 == pwd->pw_uid) {
 		SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost));
 	} else if (getdef_bool ("LOG_OK_LOGINS")) {
 		SYSLOG ((LOG_INFO, "'%s' logged in %s", username, fromhost));
@@ -1288,10 +1302,10 @@
 	closelog ();
 	tmp = getdef_str ("FAKE_SHELL");
 	if (NULL != tmp) {
-		err = shell (tmp, pwent.pw_shell, newenvp); /* fake shell */
+		err = shell (tmp, pwd->pw_shell, newenvp); /* fake shell */
 	} else {
 		/* exec the shell finally */
-		err = shell (pwent.pw_shell, (char *) 0, newenvp);
+		err = shell (pwd->pw_shell, (char *) 0, newenvp);
 	}
 	exit (err == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
 	/* NOT REACHED */




More information about the Pkg-shadow-commits mailing list